Difference between . and : in Lua

51,078

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).

Share:
51,078

Related videos on Youtube

Jason S
Author by

Jason S

Updated on December 08, 2021

Comments

  • Jason S
    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 ?

  • Jason S
    Jason S about 13 years
    ah... so it's object-oriented syntactic sugar.
  • BMitch
    BMitch about 13 years
    Exactly. 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
    Jason S about 13 years
    ooh ahh... I was going to ask where the official docs were on this, but you beat me to it. nicely done. :-)
  • Klaider
    Klaider about 8 years
    @keyle It depends on the self object will go as the first parameter and its properties value.
  • negamartin
    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) retrieves object twice, while object:method(arg) retrieves object only once. If object is a global, upvalue or table field, then : is faster than .. . is never faster than :.
  • val is still with Monica
    val is still with Monica over 5 years
    You really shouldn't worry about such stuff. If you have to, there is something just terribly wrong with your architecture.
  • DarkWiiPlayer
    DarkWiiPlayer over 5 years
    I'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
    Unknow0059 over 3 years
    Now why would you ever want to use this? Doesn't seem like it's useful for this particular case.
  • TC0072
    TC0072 over 2 years
    I'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 with x:bar(3,4), which is like x.bar(x,3,4) does the 'extra' 3rd parameter get ignored? So you'd end up with a = x (self) and b = 3?
  • N. Janné
    N. Janné about 2 years
    So what happens if you pass another object as self? x.bar(y,3,4) will this result in an error?