Reputation: 299
I'm trying to iterate over a table of functions, and call each function one by one. I keep getting the 'attempt to access a field/method NIL value. Some of them are obvious, but some of them baffle me.
tests={}
function tests.test1()
print("test1 running\n")
end
function tests.test2()
print("test2 running\n")
end
function tests.test3()
print("test3 running\n")
end
print(tests)
-- why is tests.i() or tests:i not working?
for i,x in pairs(tests) do
print("x is")
print(x)
print("i is")
print(i)
--tests.i() -- attempt to call field i a NIL value
--tests.i(tests) -- ditto
--tests:i() -- attempt to call method i, a NIl value
--tests:i(tests) -- ditto
tests[i]() -- works!
--tests.x() -- attempt to call field x, a NIl value
--tests.x(tests) -- ditto
--tests:x() -- attempt to call method x, a NIL value
--tests[x]() -- attempt to call field ? a NIl value
end
--all these work
tests.test1(tests)
tests:test1()
tests.test2(tests)
tests:test2()
tests.test3(tests)
tests:test3()
Why is the tests.i() method not working, or tests.i(tests), if it's expecting a 'self' argument, in which case why isn't tests:i() working? The last bit shows all of them working when called outside the loop, which makes it even more difficult to understand.
Upvotes: 1
Views: 445
Reputation: 28940
tests.i()
is syntactic sugar for tests["i"]()
. tests:i()
is syntactic sugar for tests["i"](tests)
.
In your loop ? for i, x in pairs(tests) do
, i
is "test1"
, "test2"
and "test3"
in the respective loop cycle. So tests[i]()
resolves to tests["test1"]()
and so forth, which is tests.test1()
Make sure you understand that tests.i
is short for tests["i"]
, not tests[i]
! So in one case you index tests
with a string "i"
while in the second case you'll index it with the value of the variable i
which in your case is one of the keys of tests
.
In a loop like yours the values are functions so you can simply call x
intead of calling tests[i]
btw.
Upvotes: 3
Reputation: 2147
that inserted-arg will get thrown away when calling tests:test1()
unless you specify a placeholder for it.
tests = {}
function tests.test1( a ) -- you can only use args you've accounted for
local a = a or ''
print( 'test1 running', a )
end
you can also call x()
to execute those functions from your loop.
-- test i, test i. 1, 2, 3?
for i, x in pairs( tests ) do
print( string.format('i is "%s"', i ) )
print( 'x is', x )
x() -- same as calling tests["i"]()
end
tests:test1()
i is "test1"
x is function: 0x1420f20
test1 running
test1 running table: 0x1421f10
Upvotes: 2