lua-users home
lua-l archive

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


RLake@oxfam.org.uk wrote:
> 
> As I understand it from the correspondence (and no doubt Edgar will correct
> me if I'm wrong), in his unified methods implementation,
> 
> a:foo(x)
> 
> is "syntactic sugar" for:
> 
> methods(a).foo(a,x)
> 
> where methods(a) is some sort of metamethod, I would guess.

It's a low level function that extracts the associated method table
that _each_ object has (it's a field in the low level data structures).
You can set it with methods(x, table).

> (Or perhaps it works recursively, which might be cool if confusing.)

Of course.  methods(methods(x)) works well and is actually used in Sol's
class system:

methods(x) is the "class table" that describes what can be done with x.
method(method(x)) is the "super class table" that describes what can be
done with "class tables" (creating instances and subclasses, perform
inheritance, ...).  And the "super class table" itself is a regular table
with no fancy features so methods(methods(methods(x))) is the same as
methods({}).  Confusing, isn't it ;-)


> Another alternative would be for
> 
> a:foo
> 
> to be "syntactic sugar" for:
> 
> curry1(methods(a), a)
> 
> where curry1 is a language primitive

Actually, the ':' is the low level primitive to access the method table.
Where a.x access field x from a, a:x access field x from methods(a).  So
this is valid:

a:x = a:x + 1
a:x:y.z = 42
a:x = function(...)...end
function a:x(...)...end

The syntactic sugar comes in when a:x is used as for a function call.
In that case, a self is automagically added as the first argument.  To call
a method without inserting the object as arg1 you have to use parenthesis.


>[...]
> a<<x>>         is defined as  getmethod_event(a, x)
> a<<x>> = v     is defined as  setmethod_event(a, v, x)
> 
> Taking this additional step makes the optimisation referred to above a
> little harder to do, since we can no longer rely on a->x returning a curry.

Actually, for Sol's first version I really started to introduce a
getmethod and setmethod event for this (and indexmethod and newmethod).
Put I dropped it pretty fast.  While it allows you to differentiate how
the access to a table is done it introduces much too much complications
and inconsistencies.

You get all these fancy features with a 3 level architecture as described
above (object, class table, super class table).  When you try to read a:x
you check the gettable and index methods for a's method table; it's a
regular table after all, so why not check it's index/gettable method
when a field is requested?  So a:x invokes Super.index(a,x) if x is not
present (Super is the super class table) or even Super.gettable(a,x)
for every x if Super.gettable is present. [1]


Ciao, ET.


[1] One is tempted to allow multiple consecutive ':' to access the
n'th method of x (so a:x invokes a::gettable(a,x)).  But I found
that you don't access the n'th method of an object very often and
then, having some kind of 'self' field in method tables (the super
class enforces this) is more versatile.  If this field is called
this_class, you can i.e. write a:this_class:gettable(x) and you can
get the method table without using the methods function by writing
a:this_class .