A Type Metatable for Tables?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

A Type Metatable for Tables?

John Hind
Reading Roberto's "Programming in Lua" 2nd Edition, I was struck by the
inconsistency between the String library and the Table library - in Lua 5.1
the former's functions can be used as methods on a String object while the
latter can only be used as "traditional" library functions.

Of course the reason is that Strings have one per-type metatable while Table
metatables are per-instance. There is currently no way for the Table library
to set a metatable for all Tables.

This could be fixed by allowing Table to have *both* a type metatable *and*
an instance metatable. There would be two choices for how this could work:

1. Setting an instance metatable could displace the type metatable
completely. This would be appropriate if we think of Tables with instance
metatables as different types from generic Tables.

2. The instance metatable could be searched first, then the type metatable.
This would be appropriate if we think of Tables with instance metatables as
sub-types of Table.

Both alternatives could be offered by having a key in the instance metatable
specifying if the type metatable should be inherited or not.

John Hind
[hidden email].


Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Miles Bader-2
"John Hind" <[hidden email]> writes:
> 1. Setting an instance metatable could displace the type metatable
> completely. This would be appropriate if we think of Tables with instance
> metatables as different types from generic Tables.
>
> 2. The instance metatable could be searched first, then the type metatable.
> This would be appropriate if we think of Tables with instance metatables as
> sub-types of Table.
>
> Both alternatives could be offered by having a key in the instance metatable
> specifying if the type metatable should be inherited or not.

It seems like 2 could be implemented using existing Lua mechanisms:
an instance metatable can just have its own metatable, with an __index
entry pointing to the global table metatable.

-Miles

-- 
Aborigines, n. Persons of little worth found cumbering the soil of a newly
discovered country. They soon cease to cumber; they fertilize.

Reply | Threaded
Open this post in threaded view
|

RE: A Type Metatable for Tables?

John Hind
While this could be set individually on each table created, it would not
work like the relationship between the String Library and the String type,
which is automatic. The advantage of type metatables is that they apply
automatically to all objects of that type while instance metatables have to
be applied to each object on or after creation.

Incidentally I find your signature quote inappropriately offensive for a
public mailing list.

-----Original Message-----
From: Miles Bader [[hidden email]] 
Sent: 20 February 2008 13:55
To: Lua list
Subject: Re: A Type Metatable for Tables?

It seems like 2 could be implemented using existing Lua mechanisms:
an instance metatable can just have its own metatable, with an __index
entry pointing to the global table metatable.

-Miles

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Greg Falcon
In reply to this post by John Hind
On 2/20/08, John Hind <[hidden email]> wrote:
> Reading Roberto's "Programming in Lua" 2nd Edition, I was struck by the
>  inconsistency between the String library and the Table library - in Lua 5.1
>  the former's functions can be used as methods on a String object while the
>  latter can only be used as "traditional" library functions.
>
>  Of course the reason is that Strings have one per-type metatable while Table
>  metatables are per-instance. There is currently no way for the Table library
>  to set a metatable for all Tables.

No, the reason you can't do this is that my_table:sort() is syntactic
sugar for my_table['sort'](my_table).

If my_table doesn't have 'sort' as a key, then my_table['sort'] sure
had better return nil, or else Lua no longer has a reliable
associative container type.

Greg F

Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Mark Meijer-2
On 20/02/2008, Greg Falcon <[hidden email]> wrote:
> On 2/20/08, John Hind <[hidden email]> wrote:
> > Reading Roberto's "Programming in Lua" 2nd Edition, I was struck by the
> >  inconsistency between the String library and the Table library - in Lua 5.1
> >  the former's functions can be used as methods on a String object while the
> >  latter can only be used as "traditional" library functions.
> >
> >  Of course the reason is that Strings have one per-type metatable while Table
> >  metatables are per-instance. There is currently no way for the Table library
> >  to set a metatable for all Tables.
>
> No, the reason you can't do this is that my_table:sort() is syntactic
> sugar for my_table['sort'](my_table).

It occurs to me that, in a sense, tables actually can have type
metatables. Not for all tables, and it's not automatic, but for tables
that are created using any of the available OOP mechanisms that Lua
supports (which of course means explicitly setting the metatable for
each instance of that type, but that is neatly hidden away in the
object creation function/method/macro/whatever).

In other words, tables that represent objects of a certain type
(class/prototype/whatever) have a type metatable. If you need a type
metatable for (almost) all your tables, then you can make a
(base)class or prototype and create all those tables as "instances" of
that type. This way, you can have your type metatable, and still let
regular tables just be regular tables.

I don't think you'd ever need or want automatic type metatables for
all tables. Firstly, metatables are themselves tables, so that would
be a problem. And secondly, it could have unexpected results for
tables created/used in/by libraries and 3rd-party code (one of the
reasons for that was mentioned above by Greg).

Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Eric Tetz
In reply to this post by John Hind
On Feb 20, 2008 4:14 AM, John Hind <[hidden email]> wrote:
> Reading Roberto's "Programming in Lua" 2nd Edition, I was struck by the
> inconsistency between the String library and the Table library - in Lua 5.1
> the former's functions can be used as methods on a String object while the
> latter can only be used as "traditional" library functions.

A string metatable doesn't pollute your string content. A table metatable does.

For instance, when you create a new table, you expect it to be empty:

   t = {}
   print(t.maxn) -- should be nil!
   print(t.sort) -- should be nil!
   ...

Having certain lookups (setn, insert, getn, foreachi, maxn, foreach,
concat, remove, sort) return non-nil values on a supposedly empty
table is going to break certain usages of a table.

If you want that behavior, you can always just use your own table constructor:

   function table.new(t)
      return setmetatable(t or {}, {__index=table})
   end

   t = table.new{ "One", "Two", "Three" }
   t:insert("Foo")
   t:insert("Bar")
   t:sort()

   for k,v in pairs(t) do print(k,v) end

Cheers,
Eric

Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Miles Bader-2
In reply to this post by Miles Bader-2
"John Hind" <[hidden email]> writes:
> While this could be set individually on each table created, it would not
> work like the relationship between the String Library and the String type,
> which is automatic. The advantage of type metatables is that they apply
> automatically to all objects of that type while instance metatables have to
> be applied to each object on or after creation.

Right, but what I was saying was that your case (2) could be implemented
using only your case (1), so there's no need for a more complex search
mechanism, only for a global default table metatable.

> Incidentally I find your signature quote inappropriately offensive for a
> public mailing list.

Actually, I agree with you ... :-/   My apologies (to you and to the list).

[I appended a big list of quotes from the "Devil's Dictionary" to my
random sig file, and neglected to remove the, er, nastier entries...]

Thanks,

-Miles

-- 
Somebody has to do something, and it's just incredibly pathetic that it
has to be us.  -- Jerry Garcia

Reply | Threaded
Open this post in threaded view
|

Re: A Type Metatable for Tables?

Ben-2
In reply to this post by Eric Tetz
On Wed, Feb 20, 2008 at 12:19 PM, Eric Tetz <[hidden email]> wrote:
>  If you want that behavior, you can always just use your own table constructor:
>
>    function table.new(t)
>       return setmetatable(t or {}, {__index=table})
>    end
>
>    t = table.new{ "One", "Two", "Three" }
>    t:insert("Foo")
>    t:insert("Bar")
>    t:sort()
>
>    for k,v in pairs(t) do print(k,v) end
>
>  Cheers,
>  Eric
>

I have done this on occassion (and it looked pretty close to exactly
the same, except I used a common default metatable).  It's fairly
simple to do, so why not that?

Ben