Josef
Josef

Reputation: 53

Regarding colon operator in Lua

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

Answers (3)

user6697869
user6697869

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

Tom Blodget
Tom Blodget

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

Yu Hao
Yu Hao

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

Related Questions