lua-users home
lua-l archive

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


Thank you again.
I will study your response carefully, but in the meanwhile ...
1) I had seen lots of examples from the lua´s authors where they express
some idea in lua.
It seems to me you have comparable mastering. And I´m understanding that I
must to learn
lua again ( _learn_ it ? ). In facts, I am considering ( and using ) lua as
an ´interpreted pascal´
( I say pascal because the begin/end pairs ) and a good ´data description
language´ but I am
losing the best part , "n´est ce pas" ?
2) But, without a deep analisys of your snippets, I still argue that ( from
lvm ) if two ´userdata´
objects have the same metatable ( i,e, they are ´the same type´ ), then any
of the methamethods
´pairs´ will be the same, and will be compared as equal.
In other words, and being a few abusing.
I have some experimental C code that ´creates´ a ´well defined´ userdata,
starting with metatable
creation ( using the ´registry´ - it only works in 5.0 - so the metatable is
never gc´ed ) and ´pushing´ the ´constructor´ function.
After that, using a C function, you can ´create´ as many ´globally binded´
´userdata´ as you like,
or allow lua code to create global or local variables of that ´type´. All
instances ( ´globally binded´ or
lua instantiated ) share the same metatable - incidentally, the metatable
itself is linked to a ´typename´
to catch, in C code, possible data (in)compatibility )
Aside the restrictions from lvm, all the stuff works ok. In other words:
being the metatable the same
for a set of  objects, any of the metamethods taken from the metatable
points to the same C function.
So, at some ´level´ ( the ´level´ at which lvm calls the ´meta function´ ) ,
they could be legitimally compared. Being a C function a unique address, I
think that the ´equality´ test ( in lvm ! ) could be
trusted !  My be here is the assimmetry: lvm is working at the ´C´ ´level´,
lua is working at the lua
´level´.
I must to think about an interesting fact I discovered near casually.
I developed two versions of a ´wrapper´ module for lua. It´s called luapi,
and the 4.0 version is
in the wiki. The 5.0 version is not, mainly because I added a lot of
interfaces ( and a lot of userdata support ) and cannot document them yet.
Also, I not tried ( or patched ) the module with 5.0b.
The entire stuff is a simplification of the official api, and a good sandbox
to learn.

One of the things I tried with 5.0 is an api function which, given a
´value´, tries to get the ´name´,
provided it´s in the global environment. It works simply getting the
key/value pairs, and checking
the given value against the ´pair´ value.

This way, I ´discovered´ the ´value´ mechanism: an object ( a ´name´ ) is
binded to a ´value´
( another object ). So the expresion
a = 5
creates two objects
the ´name´ "a"
the ´value´ "5"

after ...
b = 5
only creates a new ´name´ "b", and binds this new object to the preexistent
´value´ "5"
Function objects behave the same way
function g( )
begin
.....
end

q = g
h = g

if you try to get the ´name´ of  the ´g´ function, you will get ´h´, because
it´s ahead of ´q´
( how you knew about a ´g´function ? suppose this code
a = { fun = g, arg = 1 }
if you get the table a, then the ´index´ ´fun´, your code learns that the
value of ´fun´ is a
function, may be in the global env. How you can assert it´s a global functon
? Checking
the glob env .... but it may return the wrong result ... )

This is why and how assignment simply points a ´name´ object to a ´value´
object. My claim.

But tables are tables, and don´t lose ´object´  identity even if you modify
it, adding, deleting or changing members.
If the C code sets up a metatable, and better, the metamethods are setted up
once and forever,
I think the equality test must work in the semantic sense.
What do you think ?


----- Original Message -----
From: <RLake@oxfam.org.uk>
To: "Multiple recipients of list" <lua-l@tecgraf.puc-rio.br>
Sent: Thursday, February 20, 2003 9:45 PM
Subject: What does metamethod equality mean? (long) (Was: Re: Need for help)


>
>
> mnicolet escribió:
>
> > The whole question could be simplified to
> >  a) follow your guidelines for ´assignment´, setting ´special variables´
> >     and methods
> >  could that be done from C code ?
>
> Sure. The point of the page is to show how to do it, but it could
> easily be implemented in C. If I have time, I'll hack something
> together.
>
> >  b) hack a bit the lvm.
>
> I think your suggestion for __lt is a reasonable compromise. However,
> there is a slight issue with what "the same metamethod" means.
>
> Consider the following code:
>
> --------------------------------
> Code snippet 1
> --------------------------------
>
> function compare_by_id(self)
>   local function lt(a, b)
>        return a.id < b.id
>   end
>
>   local meta = getmetatable(self)
>   if meta then meta.__lt = lt
>           else setmetatable(self, {__lt = lt}
>   end
>   return self
> end
>
>
> a = compare_by_id {id = 2}
> b = compare_by_id {id = 3}
>
> if a < b then print "a is less"
>          else print "b is less"
> end
>
> ----------------------------------
>
> Now, 'a' and 'b' have different metatables. But that should be
> ok because they have the same __lt metamethod, right? Wrong!
> Every time compare_by_id runs, it returns a different "closure".
> (A closure is a compiled function with a list of upvalues. Even
> though there are no upvalues in the above functions, you get
> a new closure every time you execute the function statement.
>
> To make that clearer, suppose the function which creates the
> __lt method looked like this:
>
> --------------------------------
> Code snippet 2
> --------------------------------
>
> function compare_by_named_key(key, self)
>   local function lt(a, b)
>     return a[key] < b[key]
>   end
>
>   local meta = getmetatable(self)
>   if meta then meta.__lt = lt
>           else setmetatable(self, {__lt = lt}
>   end
>   return self
> end
>
> ----------------------------------
>
> Now 'key' is a "closed variable" in 'lt' so the two closure
> instances are obviously different:
>
> ----------------------------------
> Example 2.1
> ----------------------------------
>
> a = compare_by_named_key("apples", {apples = 2})
> b = compare_by_named_key("oranges", {oranges = 3})
>
> ----------------------------------
>
> Then the comparison 'a < b' is comparing apples with oranges. :)
> But in the following case, I would like it to work:
>
> ----------------------------------
> Example 2.2
> ----------------------------------
>
> a = compare_by_named_key("apples", {apples = 2})
> b = compare_by_named_key("apples", {apples = 3})
>
> ----------------------------------
>
> It won't, though.
>
> Now, the first example could be fixed by lifting the definition
> of lt out of compare_by_id:
>
> ----------------------------------
> Code snippet 3
> ----------------------------------
>
> do
>   local function lt(a, b)
>     return a.id < b.id
>   end
>
>   function compare_by_id(self)
>     local meta = getmetatable(self)
>     if meta then meta.__lt = lt
>             else setmetatable(self, {__lt = lt})
>     end
>     return self
>   end
> end
>
> ----------------------------------
>
> In this case, there is only one closure of 'lt' and
> so 'a' and 'b' will end up with different metatables but
> the same __lt metamethod.
>
> That won't help with the second example, though. There
> is a workaround, but it is more complicated; I have to
> put the key name into the metatable, too, something
> like this:
>
> ----------------------------------
> Code snippet 4
> ----------------------------------
>
> do
>   local function lt(a, b)
>     local akey, bkey = getmetatable(a).sortkey,
>                        getmetatable(b).sortkey
>     return akey == bkey and a[akey] < b[bkey]
>   end
>
>   function compare_by_named_key(key, self)
>     local meta = getmetatable(self)
>     if meta then meta.sortkey, meta.__lt = key, lt
>             else setmetatable(self, {sortkey = key,
>                                      __lt = lt})
>     end
>     return self
>   end
> end
>
> ----------------------------------
>
> However, that is a lot more complicated (and slower), and it
> is just a simple example.
>
> In Lua 4, (and with c-closures in Lua 5), we could say that
> two closures are the same if there functions are the same
> and the list of upvalues in the closures are element by
> element equal. That won't work in Lua 5, though, because
> Lua 5 has full lexical binding and no longer has constant
> upvalues (in Lua functions). So going back to Example 2.2,
> the two different instances of 'lt' have *different* 'key'
> upvalue objects which happen to have the same value.
>
> It is clear from a syntactic analysis of the code in Snippet 2
> that 'key' is a constant, but Lua does not (currently) do this
> analysis. Otherwise, it could create a constant upvalue vector
> instead of a variable upvalue vector, and the element-by-element
> comparison would still work.
>
> Regardless, we would end up with a fairly time-consuming test
> for metamethod comparison. It still might be faster than the
> multiple function calls and hash lookups of Code Snippet 4,
> though.
>
> Furthermore, Code Snippet 2 is (at least theoretically) better
> because it makes it clear that the comparison key is fixed. In
> Code Snippet 4, I could legally change the name of the
> comparison key at any time (unless the metatable itself is
> locked, but even that cannot easily be worked out by
> syntactic analysis.)
>
> > What is ´binary dispatch´ ? may it be something like the simple code I´m
> > thinking about ?
>
> It is where you consult the types of both operands at the same time.
> A few languages implement this (Dylan, for example, and I believe there
> is a Java dialect which does it.) In the case of non-inherited types, it
> is easy; you just have a hash table of type pairs. But inheritance makes
> it trickier and multiple inheritance makes it even trickier still.
> Automatic
> type coercion is also complicated.
>
> I'll see if I can dig up some web references rather than doing a long
> essay.
>
>