Reputation: 53
Why does this piece of code fail (attempt to call method 'sort' (a nil value))
th> xyz = {1,2,3}
th> xyz:sort()
while this works
th> table.sort(xyz)
Upvotes: 3
Views: 599
Reputation:
It's because xyz
doesn't have a key/value pair where the key is "sort"
and the value is a function. table
has said key/value pair. Try this to make things clearer:
local xyz = {}
print(xyz.sort) -- prints nil
print(table.sort) -- prints function: 0xabcd1234
Upvotes: 0
Reputation: 20812
@YuHao gives a direct answer. This is more background.
The colon operator is an indexing operator; It indexes the value of the expression on the left with the identifier (as a string-typed key) on the right.
expression:identifier(arg0, arg1, ...)
is conceptually the same as
local lhs = expression
lhs.identifer(lhs, arg0, arg1, ...)
is conceptually the same as
local lhs = expression
lhs["identifer"](lhs, arg0, arg1, ...)
So, your question isn't so much about the colon operator as it is about indexing.
In Lua, indexing a table-typed value first checks the table's fields for the key. If found, it returns the value.
If not, it checks the table for its one optional currently associated metatable and if that table has a value with the key "__index". If not found, the result of indexing is nil
. If the value of the __index field is a table, the process repeats on that table. If the value is a function, then the result of indexing is the return value of calling that function.
In your case, as @YuHao explains, your table doesn't have a "sort" field nor a metatable so the indexing result is nil
, resulting in the error of attempting to call a nil value. (The message nicely indicates that you used the colon syntax by saying it is a "method call".)
Upvotes: 4
Reputation: 122493
Because the table
table, which contains the generic functions for manipulating tables provided by the standard library, isn't in the metatable for a table by default. In fact, a table doesn't have a metatable unless specified explicitly.
You could do this manually though:
local xyz = {1,2,3}
local mt = { __index = table}
setmetatable(xyz, mt)
xyz:insert(2)
xyz:sort()
Upvotes: 10