3 ms·
Nah; regular old Lua 5.1. The colon syntax is just syntactic sugar -- self isn't actually bound. function Foo:Bar(baz) is the same as Foo.Bar = function(self,
by cheald 15y ago
Nah; regular old Lua 5.1. The colon syntax is just syntactic sugar -- self isn't actually bound.
function Foo:Bar(baz) is the same as Foo.Bar = function(self, baz); invoking Foo:Bar("rebar") is sugar for Foo.Bar(Foo, "rebar"). self is never bound - it's just passed in (explicitly, via . syntax, or implicitly, vs : syntax). In all cases, the caller is always specified.
You can pass Foo.Bar around (as it's a function reference), but if you have something like:
Foo = {}
function Foo:Bar(baz)
print(baz)
end
local baz = Foo.Bar
Then baz has no binding information to Foo; defining the function with the : syntax is just syntactic sugar. To invoke, you would have to call:
baz(Foo, "woohoo")
Just calling
baz("woohoo")
populates self with "woohoo", and the bar parameter would be nil, demonstrating that there is no contextual binding to the function itself.
- premchai21 15y agoWhat do you mean “isn't actually bound”? The function being defined using colon syntax doesn't close over self, since it's a parameter—but functions defined within that function will close over the self parameter, since it's a local from an enclosing scope: foo = { x = 3 } function foo:bar(baz) return function(thud) return thud + baz + self.x end end womble = foo:bar(4) womble(7) --> 14 Python I believe also closes over self as a variable, and Ruby has similar behavior for local procs, even though « self » is a special form in Ruby. This is in distinct contrast to JavaScript, where the value of the special form « this » goes nuts inside closures because it's attached to the function: foo = { x: 3 }; foo.bar = function(baz) { return function(thud) { return thud + baz + this.x; }; }; womble = foo.bar(4); womble(7) # --> NaN So in what way are you placing Lua and JavaScript together, and Python and Ruby together? [slightly rearranged for clarity]
- cheald 15y agoAh, okay, I see what you mean. Yeah, you're absolutely right there. Point conceded. Mentally, I was separating Javascript and Lua from Ruby because while the caller is explicitly passed in Javascript and Lua (either via call/apply, or as a parameter), Ruby methods are implicitly aware of their scope (and can't really be referentially passed around like Javascript or Lua methods). Lua "methods" aren't aware of their scope (though closures are.
- premchai21 15y agoRuby methods bound to their objects can be passed around; it's just a bit more cumbersome, in the form of « m = obj.method(:foo) » followed by « m.call(…) ». You can even do « m = :foo.to_proc » in recent Ruby and be able to « m.call(obj, …) »; this is quite useful for things like « [1, 2, 3].inject(&:+) ». So we have that Python's dot always binds, Ruby's dot always calls, and Lua's dot is always a table lookup, with Lua's colon being a separate syntax for (always) the compound operation with injected self-argument. And then JavaScript is the schizophrenic one: « obj.foo(bar) » is not the same as « var y = obj.foo; y(bar) ». Property lookup and function call insert a hidden step between them when and only when directly composed, and a function call without an immediately adjacent property lookup in a way injects the opposite step of making « this » in the callee be the global object (I think). “Politicians lie in cast iron sinks.”