Meta table error - lua

I am trying to set up a toy example for threading in torch but I am getting an error from running the code below. I think it might just be the way I set up the table but I am not sure.
Threads = require 'threads'
Threads.serialization('threads.sharedserialize')
DataThreads = {}
DataThreads.__index = DataThreads
local result = {}
local unpack = unpack and unpack or table.unpack
function DataThreads.new(nThreads,opt_)
local self = {}
opt_ = opt_ or {}
self.threads = Threads(nThreads,
function()
print("background stuff")
end
)
self.threads:synchronize()
-- The below for loop is causing the error but the same :addjob() works later on
for i=1, nThreads do
self.threads:addjob(self._getFromThreads, self._pushResult)
end
return setmetatable(self,DataThreads)
end
function DataThreads._getFromThreads()
x,y = torch.uniform(),torch.uniform()
return x,y
end
function DataThreads._pushResult(...)
local res = {...}
if res == nil then
self.threads:synchronize()
end
result[1] = res
end
function DataThreads:getBatch()
self.threads:addjob(self._getFromThreads, self._pushResult)
self.threads:dojob()
local res = result[1]
result[1] = nil
if torch.type(res) == 'table' then
return unpack(res)
end
print(type(res))
return res
end
d = DataThreads.new(4)
The error occurs in :addjob() in the .new function. However calling the same :addjob() later on in the :getBatch() function works. Am I not allowed to call the ._getFromThreads(), ._getFromThreads() functions before the metatable is set? Here is the error, which I think means ._getFromThreads() is not returning anything;
/home/msmith/torch/install/bin/luajit: ...e/msmith/torch/install/share/lua/5.1/threads/threads.lua:215: function callback expected
stack traceback:
[C]: in function 'assert'
...e/msmith/torch/install/share/lua/5.1/threads/threads.lua:215: in function 'addjob'
threads.lua:21: in function 'new'
threads.lua:54: in main chunk

When the code in your new function runs the metatable hasn't been set up yet so when you use self._getFromThreads and self._pushResult there's nothing there and you get nil back and that's not valid.
It works after the new function returns because at that point the metatable has been added so the lookups use the __index metamethod to look the entries up.
You can do
local self = setmetatable({}, DataThreads)
to set the metatable up immediately and then just
return self
at the end.

Related

LUA using function variable outside of it

I am trying to edit a script in LUA but I couldn't get access of a local defined in a function
LUA Code
function getSafeMoney()
local SafeMoney = nil
QBCore.Functions.ExecuteSql(false, 'SELECT * FROM `moneysafes` WHERE `safe` = "mechanic"', function(result)
SafeMoney = json.decode(json.encode(result[1])).money;
end)
return SafeMoney
end
print(getSafeMoney())
Result :
nil
here's the sql function as sysdevs asked
QBCore.Functions.ExecuteSql = function(wait, query, cb)
local rtndata = {}
local waiting = true
exports['ghmattimysql']:execute(query, {}, function(data)
if cb ~= nil and wait == false then
cb(data)
end
rtndata = data
waiting = false
end)
if wait then
while waiting do
Citizen.Wait(5)
end
if cb ~= nil and wait == true then
cb(rtndata)
end
end
return rtndata
end
Your second function is not holding the main function I assume, I am bad at lua aswell, but I think that changing
QBCore.Functions.ExecuteSql(false, ............
to
QBCore.Functions.ExecuteSql(true, ............
This will probably fix your problem, still your code is ambiguous and needs concentration if you could provide more information I might be able to help more

bad argument #1 to 'insert' (table expected, got nil) error in love2d lua

i keep receiving an error when i try to run my lua script.
The error is: bad argument #1 to 'insert' (table expected, got nil)
here is my gameloop code:
local GameLoop = {}
local insert = table.insert
local remove = table.remove
function GameLoop:create()
local gameLoop = {}
function gameLoop:addLoop(obj)
insert(self.clocks,obj)
end
function gameLoop:update(dt)
for clocks = 0,#self.clocks do
local obj = self.clocks[clocks]
if obj ~= nil then
obj:tick(dt)
end
end
end
return gameLoop
end
return GameLoop
From the code you've shown, your gameLoop tables do not contain a clocks member, so really you are passing nil to the first argument of insert(self.clocks, obj).
Simple fix is to add that member.
local gameLoop = { clocks = {} }
As an aside, it's usually better to write this type of construct using metatables, since it reduces function duplication.
local insert, remove =
table.insert, table.remove
local GameLoop = {}
GameLoop.__index = GameLoop
function GameLoop:create ()
return setmetatable({
clocks = {}
}, self)
end
function GameLoop:addLoop (obj)
insert(self.clocks, obj)
end
function GameLoop:update (dt)
for _, clock in ipairs(self.clocks) do
obj:tick(dt)
end
end
return GameLoop

infinite recursion in __index metamethod

As I understand lua don't call __index unless the key wasn't found in the table so I have that code and it suffers from infinite recursion in the __index part which I don't get as both values used inside the __index function already exist in the table!?
This is basically a test script for trying to save the size of the table in a memory to retreive when # is called
do
local lenKey,originalKey = {},{}
fastKey = {}
fastKey.__len = function(t) return t[lenKey] end
fastKey.__index = function (t,k)
t[lenKey] = t[lenKey] +1
return t[oroginalKey][k]
end
fastKey.__newindex = function(t,k,v) t[originalKey][k] = v end
fastKey.__pairs = function ()
return function (t, k)
return next(t[oroginalKey], k)
end
end
function fastLen(t)
local proxy = {}
local c = 0
for _ in pairs(t) do
c=c+1
end
proxy[lenKey] = c
proxy[originalKey] = t
setmetatable(proxy,fastKey)
return proxy
end
end
n = fastLen{1,2,3,x=5}
--n:insert(1) -- here the __index is called and gets stackoverflow
print(#n)
You've got two typos in there: both the __index and __pairs functions contain oroginalKey instead of originalKey.

Is This A lua Variable Scope Issue (and how can it be solved)?

A very strange error, showing an object is nil.
the code in subject is
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
...
One would think, that if pbs:HasNext() is true, it means that, pbs is not nil, whatsoever.
However, the print(pbs) - the first line of HTMLEntityCodec:DecodeCharacter prints nil
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
...
The entire file dumped below, it was stripped from 1800+ lines to 110 so it can be clear for SO users to get he context. But that stripping took away all logic from the code, so do not get confused by that.
#!/usr/bin/env lua
function Inherits( baseClass )
local new_class = {}
local class_mt = { __index = new_class }
function new_class:create()
local newinst = {}
setmetatable( newinst, class_mt )
return newinst
end
if baseClass then
setmetatable( new_class, { __index = baseClass } )
end
return new_class
end
-------------------------------------------
-- PushbackString
-------------------------------------------
PushbackString = Inherits({})
function PushbackString:Init(input)
self.input = input
self.pushback = nil
self.temp = nil
self.index = 0
self.mark = 0
end
-- Mark the current index, so the client can reset() to it if need be.
function PushbackString:HasNext()
return true
end
function PushbackString:Mark ()
self.temp = self.pushback
self.mark = self.index
end
BaseCodec = Inherits({})
function BaseCodec:Decode(input)
local buff = ''
local pbs = PushbackString:create()
pbs:Init(input)
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
if char ~= nil then
buff = buff .. char
else
buff = buff .. pbs:Next()
end
end
return buff
end
HTMLEntityCodec = Inherits(BaseCodec)
-- HTMLEntityCodec.classname = ('HTMLEntityCodec')
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
pbs:Mark()
end
DefaultEncoder = Inherits({})
function DefaultEncoder:Init(codecs)
self.html_codec = HTMLEntityCodec:create()
end
function DefaultEncoder:TestInput(input , strict)
print ("\n----------------8<----------------8<----------------\n")
print ("Input:\t" .. input)
-- default value
if strict == nil then strict = true end
-- nothing to do
if input == nil then return nil end
local working = input
local codecs_found = {}
local found_count = 0
local clean = false
while not clean do
clean = true
old = working
working = self.html_codec:Decode( working )
if old ~= working then
print ("Warning:\tINTRUSION DETECTED")
end
end
print ("Output:\t".. working)
return working
end
local default_encoder = DefaultEncoder:create()
default_encoder:Init()
default_encoder:TestInput("%25", true)
----------8<-----------8<--------------8<----------------
END OF FILE
Console Output:
tzury#1005:~/devel/lua$ lua problem.lua
----------------8<----------------8<----------------
Input: %25
nil
lua: problem.lua:70: attempt to index local 'pbs' (a nil value)
stack traceback:
problem.lua:70: in function 'DecodeCharacter'
problem.lua:54: in function 'Decode'
problem.lua:96: in function 'TestInput'
problem.lua:109: in main chunk
[C]: ?
In your code, the crash happens on this line:
local char = self.DecodeCharacter(pbs)
The problem is that you are calling DecodeCharacter with incorrect number of arguments.
Solution: call it like this (notice the colon):
local char = self:DecodeCharacter(pbs)
Explanation:
When you define functions in Lua using the colon (:), you are using a syntax sugar which hides an implicit first argument named self. Definitions like:
function HTMLEntityCodec:DecodeCharacter(pbs) ... end
Are actually 'translated' to this:
HTMLEntityCodec.DecodeCharacter = function (self, pbs) ... end
When you call the function, you either need to pass the self argument yourself, or use the colon call to supply it automatically. In your code (self.DecodeCharacter(pbs)), you are passing pbs which ends up as self in HTMLEntityCodec.DecodeCharacter, and pbs ends up being nil. Both following calls are equivalent and should solve the issue:
local char = self.DecodeCharacter(self, pbs)
local char = self:DecodeCharacter(pbs)

How does the __call metamethod in Lua 5.1 actually work?

I'm trying, as an exercise, to make a set implementation in Lua. Specifically I want to take the simplistic set implementation of Pil2 11.5 and grow it up to include the ability to insert values, delete values, etc.
Now the obvious way to do this (and the way that works) is this:
Set = {}
function Set.new(l)
local s = {}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.insert(s, v)
s[v] = true
end
ts = Set.new {1,2,3,4,5}
Set.insert(ts, 5)
Set.insert(ts, 6)
for k in pairs(ts) do
print(k)
end
As expected I get the numbers 1 through 6 printed out. But those calls to Set.insert(s, value) are really rather ugly. I'd much rather be able to call something like ts:insert(value).
My first attempt at a solution to this looked like this:
Set = {}
function Set.new(l)
local s = {
insert = function(t, v)
t[v] = true
end
}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
This works mostly fine until you see what comes out of it:
1
2
3
4
5
6
insert
Very obviously the insert function, which is a member of the set table, is being displayed. Not only is this even uglier than the original Set.insert(s, v) problem, it's also prone to some serious trouble (like what happens if "insert" is a valid key someone is trying to enter?). It's time to hit the books again. What happens if I try this instead?:
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__call = Set.call})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(f)
return Set[f]
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't exist to be called means that the ts metatable is going to be searched for "__call".
The ts metatable's "__call" key returns Set.call.
Now Set.call is called with the name insert which causes it to return the Set.insert function.
Set.insert(ts, 5) is called.
What's really happening is this:
lua: xasm.lua:26: attempt to call method 'insert' (a nil value)
stack traceback:
xasm.lua:26: in main chunk
[C]: ?
And at this point I'm stumped. I have absolutely no idea where to go from here. I hacked around for an hour with varying degrees of increasingly desperate variations on this code but the end result is that I have nothing that works. What undoubtedly obvious thing am I overlooking at this point?
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't exist to be called means that the ts metatable is going to be searched for "__call".
There's your problem. The __call metamethod is consulted when the table itself is called (ie, as a function):
local ts = {}
local mt = {}
function mt.__call(...)
print("Table called!", ...)
end
setmetatable(ts, mt)
ts() --> prints "Table called!"
ts(5) --> prints "Table called!" and 5
ts"String construct-call" --> prints "Table called!" and "String construct-call"
Object-oriented colon-calls in Lua such as this:
ts:insert(5)
are merely syntactic sugar for
ts.insert(ts,5)
which is itself syntactic sugar for
ts["insert"](ts,5)
As such, the action that is being taken on ts is not a call, but an index (the result of ts["insert"] being what is called), which is governed by the __index metamethod.
The __index metamethod can be a table for the simple case where you want indexing to "fall back" to another table (note that it is the value of the __index key in the metatable that gets indexed and not the metatable itself):
local fallback = {example = 5}
local mt = {__index = fallback}
local ts = setmetatable({}, mt)
print(ts.example) --> prints 5
The __index metamethod as a function works similarly to the signature you expected with Set.call, except that it passes the table being indexed before the key:
local ff = {}
local mt = {}
function ff.example(...)
print("Example called!",...)
end
function mt.__index(s,k)
print("Indexing table named:", s.name)
return ff[k]
end
local ts = {name = "Bob"}
setmetatable(ts, mt)
ts.example(5) --> prints "Indexing table named:" and "Bob",
--> then on the next line "Example called!" and 5
For more information on metatables, consult the manual.
You said:
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't
exist to be called means that the ts metatable is going
to be searched for "__call".
The ts metatable's "__call" key returns Set.call.
Now Set.call is called with the name insert which causes
it to return the Set.insert function.
Set.insert(ts, 5) is called.
No, what happens is this:
When insert isn't found directly in the ts object, Lua looks for __index in its metatable.
If it is there and it is a table, Lua will search for insert there.
If it is there and it is a function, it will call it with the original table (ts in this case) and the key being searched for (insert).
If it isn't there, which is the case, it is considered nil.
The error you're having is because you don't have __index set in your metatable, so you are effectively calling a nil value.
This can be solved by pointing __index to some table, namely Set, if you're going to store your methods there.
As for __call, it is used for when you call the object as a function. Ie:
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__index=Set, __call=Set.call})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(s, f)
-- Calls a function for every element in the set
for k in pairs(s) do
f(k)
end
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
ts(print) -- Calls getmetatable(ts).__call(ts, print),
-- which means Set.call(ts, print)
-- The way __call and __index are set,
-- this is equivalent to the line above
ts:call(print)
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__index=Set})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(f)
return Set[f]
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
I modified your first version and this version would offer the features I think you are looking for.
Set = {}
Set.__index = Set
function Set:new(collection)
local o = {}
for _, v in ipairs(collection) do
o[v] = true
end
setmetatable(o, self)
return o
end
function Set:insert(v)
self[v] = true
end
set = Set:new({1,2,3,4,5})
print(set[1]) --> true
print(set[10]) --> nil
set:insert(10)
print(set[10]) --> true

Resources