lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I believe this has been discussed before on the list,
but I can't find it...  Here are two problems with dot
passing a silent self; there may be others.

The first problem has to do with functions as first-class
values.  What looks like method invocation to us:

   object.method()

is semantically a table lookup followed by a function call:

   (object.method) ()

So, that ought to behave identically to this:

   foo = object.method;
   foo()

as well as this:

   function bar ()  return object.method  end
   bar()()

If method invocation had to pass "object" to "method", the
only way all of those forms could behave identically was if
"foo" (that is, the value returned by "object.method") was
not a naked function reference, but rather a delegate that
held both the function and the object it was looked up from.

Which might be kind of interesting, actually.  But you would
get into issues of how the == operator should work for these
delegates (should two function values compare inequal
because they were looked up from different tables?  Or should
they compare equal but cause different behavior?) and 
possibly a bunch of other issues.

A second problem can be seen in Javascript.
Javascript does something similar to what you
describe.  A hidden variable "this" is set
to the method's object, or undefined if the function
is called solo.  Because "this" doesn't behave like
a normal (visibly-declared) lexically-scoped variable,
there can be Great Unpleasantness when mixing
OO and  functional programming:

  object = { x:1, y:2 };
  assert( object.getSum() == 3 );

  // INCORRECT, because "this" is undefined within getX()
  object.getSum = function () {
     function getX () { return this.x }
     function getY () { return this.y }
     return getX() + getY();
  }

  // Correct, but sort of defeats the whole purpose.
  object.getSum = function () {
     var self = this;
     function getX () { return self.x }
     function getY () { return self.y }
     return getX() + getY();
  }

This is, of course, much more insideous when the
functions are more complicated.

The problem doesn't happen In Lua because the
declaration of "self" is explicitly specified by the colon:

   function object:getSum ()   -- colon declares "self"
        function getX ()  return self.x  end
        function getY ()  return self.y  end
        return getX() + getY();
   end

getX() correctly inherits "self" from getSum()
because getX() has no colon near it.