While I don't really know Lua, this is a rather unexpected and bizarre behavior.
Let's say I have my_module.lua:
local function dump(o) -- SO:9168058
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
local mymodule = {}
function mymodule.myfunction(indict)
print(dump(indict))
end
return mymodule
Ok, now I run this:
lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"
This should not be complicated - I "import" the module, and call a function in it with an argument that is an object (the table/associative array/dictionary {aa=12}). Then I simply try to print this argument from within the function. However, I get this:
$ lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"
{ ["myfunction"] = function: 0x5619aeddf770,}
So, the response to print(dump(indict)) inside myfunction, where indict is an argument passed to myfunction, Lua prints .... "myfunction" ????!
I cannot even wrap my head around this - how can this possibly happen ?
And how can I pass an object as an argument to a function, such that when I print the argument from within the function, the object which is the argument is printed - and not the function itself ??!
Btw, the same happens even if I just pass a number instead of an object, say:
lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"
EDIT: did a bit of debugging - so with this:
function mymodule.myfunction(indict)
print(indict)
print(dump(indict))
end
... I get this printout when using a numeric argument:
$ lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"
table: 0x55f15a7a07a0
{ ["myfunction"] = function: 0x55f15a7a07e0,}
... so it simply doesn't see this number anywhere, but the function sees itself as the first argument.
This reminded me, how in a Python class, you have to write methods as functions with "self" as first argument, so I tried this:
function mymodule.myfunction(self, indict)
print("self", self, "indict", indict)
print(dump(indict))
end
... which prints:
$ lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"
self table: 0x560510b5a7d0 indict 42
42
... or in case of passing an obect:
$ lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"
self table: 0x55d51c9d5800 indict table: 0x55d51c9d5880
{ ["aa"] = 12,}
... well, that's more like it ...
Can anyone explain where does this come from - why do I need to add a "self" argument in this case?
In lua, the call a:b(x) passes a reference to the object a as the first (self) parameter to the function b.
Since your module definition is:
function mymodule.myfunction(indict)
and the call statement is mm:myfunction, the object/table mm is passed as the first parameter (which here is indict).
Either change the function definition to
function mymodule:myfunction(indict)
if you want to keep call like mm:myfunction, or call the function as mm.myfunction.
The behaviour is discussed in detail in the PiL book on OOP concepts.
The effect of the colon is to add an extra hidden parameter in a method definition and to add an extra argument in a method call. The colon is only a syntactic facility, although a convenient one; there is nothing really new here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With