Difference between . and : in Lua
Solution 1
The colon is for implementing methods that pass self
as the first parameter. So x:bar(3,4)
should be the same as x.bar(x,3,4)
.
Solution 2
For definition it is exactly the same as specifying self manually - it will even produce same bytecode on compilation. I.e. function object:method(arg1, arg2)
is same as function object.method(self, arg1, arg2)
.
On use :
is almost the same as .
- a special kind of call will be used internally to make sure object
and any possible side-effects of calculations/access are calculated only once. Calling object:method(arg1, arg2)
is otherwise same as object.method(object, arg1, arg2)
.
Solution 3
To be completely precise, obj:method(1, 2, 3)
is the same as
do
local _obj = obj
_obj.method(_obj, 1, 2, 3)
end
Why the local variable? Because, as many have pointed out, obj:method()
only indexes _ENV
once to get obj
. This normally just important when considering speed, but consider this situation:
local tab do
local obj_local = { method = function(self, n) print n end }
tab = setmetatable({}, {__index = function(idx)
print "Accessing "..idx
if idx=="obj" then return obj_local end
end})
end
tab.obj.method(tab.obj, 20)
--> Accessing obj
--> Accessing obj
--> 20
tab.obj:method(10)
--> Accessing obj
--> 10
Now imagine the __index
metamethod did more than just printing something. Imagine it increased a counter, logged something to a file or deleted a random user from your database. There's a big difference between doing that twice or only once. In this case, there's a clear difference between obj.method(obj, etc)
and obj:method(etc)
.
Related videos on Youtube
Jason S
Updated on December 08, 2021Comments
-
Jason S over 2 years
I am confused about the difference between function calls via
.
and via:
> x = {foo = function(a,b) return a end, bar = function(a,b) return b end, } > return x.foo(3,4) 3 > return x.bar(3,4) 4 > return x:foo(3,4) table: 0x10a120 > return x:bar(3,4) 3
What is the
:
doing ?-
Saurabh about 13 years
-
-
Jason S about 13 yearsah... so it's object-oriented syntactic sugar.
-
BMitch about 13 yearsExactly. In the entire reference manual, the only blurb they give on this is "The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self." (5.0 manual, bottom of pdf page 19)
-
Jason S about 13 yearsooh ahh... I was going to ask where the official docs were on this, but you beat me to it. nicely done. :-)
-
Klaider about 8 years@keyle It depends on the
self
object will go as the first parameter and its properties value. -
negamartin over 7 years@keyle Colon syntax would be a little faster if the object you're calling is not a local, since the virtual machine retrieves it only once. Basically dot syntax like
object.method(object,args)
retrievesobject
twice, whileobject:method(arg)
retrievesobject
only once. Ifobject
is a global, upvalue or table field, then:
is faster than.
..
is never faster than:
. -
val is still with Monica over 5 yearsYou really shouldn't worry about such stuff. If you have to, there is something just terribly wrong with your architecture.
-
DarkWiiPlayer over 5 yearsI'd say it's the other way around; good code should not make any assumptions about implementation details of unrelated code. Function calls may or may not be memoized, that doesn't mean it's good practice to call them more often than needed.
-
Unknow0059 over 3 yearsNow why would you ever want to use this? Doesn't seem like it's useful for this particular case.
-
TC0072 over 2 yearsI've just found this type of code in a plugin I'm trying to understand. I wanted to check something, if the function should only have 2 parameters like
function bar(a, b)
. If you call it withx:bar(3,4)
, which is likex.bar(x,3,4)
does the 'extra' 3rd parameter get ignored? So you'd end up witha = x
(self) andb = 3
? -
N. Janné about 2 yearsSo what happens if you pass another object as self?
x.bar(y,3,4)
will this result in an error?