lua-users home
lua-l archive

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


Ambivalent use of functions in both functionnal notation and oo notation would require to instrument all these functins to accept conditionnaly a self parameter. Example of these functions are in the string stdlib:

local str = "foobarfoo"

local substr1 = str:match("foo(.*)foo")
local substr2 = string.match(str, "foo(.*)foo")

Writing such a function in Lua would be add unnecessary complications:

function string.match(s, pattern, init)
    if self then
        init = pattern
        pattern = s
        s = self
    end
    -- Do the actual stuff
    ...
end

And as a final word, if you want a symmetry with other OO languages, you can simply consider that the Lua "." correspond to the C++ "::" operator, and the Lua ":" is the C++ ".".

-----Message d'origine-----
De : lua-bounces@bazar2.conectiva.com.br [mailto:lua-bounces@bazar2.conectiva.com.br] De la part de Bret Victor
Envoyé : 14 septembre 2006 04:08
À : lua@bazar2.conectiva.com.br
Objet : Re: Why a : (colon) operator?

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.