Diferencia entre . y: en Lua

Estoy confundido acerca de la diferencia entre las llamadas a funciones a través de . y vía :

 > 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 

¿Qué es el : hacer?

El colon es para implementar métodos que se pasan a self como el primer parámetro. Entonces x:bar(3,4) debe ser lo mismo que x.bar(x,3,4) .

Por definición, es exactamente lo mismo que especificarse manualmente: incluso producirá el mismo código de bytes en la comstackción. Es decir function object:method(arg1, arg2) es igual que la function object.method(self, arg1, arg2) .

En uso : es casi lo mismo que . – Se utilizará un tipo especial de llamada internamente para garantizar que el object y los posibles efectos secundarios de los cálculos / acceso se calculan solo una vez. object:method(arg1, arg2) llamante object:method(arg1, arg2) es lo mismo que object.method(object, arg1, arg2) .

Para ser completamente preciso, obj:method(1, 2, 3) es lo mismo que

 do local _obj = obj _obj.method(_obj, 1, 2, 3) end 

¿Por qué la variable local? Porque, como muchos han señalado, obj:method() solo indexa _ENV una vez para obtener obj . Esto normalmente solo es importante cuando se considera la velocidad, pero considere esta situación:

 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 

Ahora imagine que el __index __index hizo más que solo imprimir algo. Imagine que aumentó un contador, registró algo en un archivo o eliminó un usuario aleatorio de su base de datos. Hay una gran diferencia entre hacerlo dos veces o solo una vez. En este caso, hay una clara diferencia entre obj.method(obj, etc) y obj:method(etc) .