[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Type Metatables for Table and Userdata - Powerpatch
- From: "John Hind" <john.hind@...>
- Date: Fri, 7 Dec 2012 16:08:58 -0000
Interesting comments. I thought it might clarify things if I explain my
motivation for these Powerpatches. First let me be clear: I understand and
greatly value Lua's philosophy of providing 'mechanisms' not policies, these
patches are intended to do this, not to either enforce or preclude any
programming paradigm. Having said that, my motivation is to support a more
comfortable OO programming style as a layer on top of these generic
mechanisms. My plea is this: if you are not a fan of OO then just ignore
these mechanisms or better still think about ways they could be used to
improve your chosen paradigm!
I want to create OO objects like this:
obj = ({"item1","item2","item3"}):class("list")
Ideally the round brackets would not be necessary, but I'd rather not mess
with parsing! 'class' is a method from the type metatable for Table type. It
fetches a factory closure from a private table of classes, keyed "list", the
class name in this case. This stores the class metatable in an upvalue. For
classes based on Table type, running the closure validates the input table
and attaches the metatable returning the table converted in situ. For
classes based on Userdata type, it creates the userdata, uses the table to
initialise it and returns that, discarding the table. 'class' then returns
the object. The same syntax can be used to convert a named object from one
class to another:
obj = obj:class("bag")
In an OO paradigm, the Lua table type is a mechanism supporting type
extension using classes. Some of these classes will be containers of various
sorts, and generally speaking each container class has 'one true way' of
iterating it. If it has more than one way, it probably ought to be more than
one class (there are exceptions, see below). In this context, 'for {items}
in {container} do' seems the most natural thing in the world (and the idea
of items being 'in' a function seems outlandish!). Other paradigms, other
mindsets! So for example:
for item in mylist do -- like 'ipairs', but values only, produced in
key order.
for member in myset do -- keys only, in arbitrary order, value is always
'true'.
for name,value in mybag do -- property bag produces key and value (like
pairs()).
However, there are some cases were a choice of more than one iterator may be
appropriate, in which case the iterator should be returned by a method of
the class:
for file in myfolder:files() do -- produce the files in a folder
for folder in myfolder:folders() do -- produce the sub-folders in the same
folder
(OK, we're back to items being 'in' a function, but just think of the method
as accessing a sub-container within the object.) This can also be used if
the iterator needs to be parameterised.
The case for 'pairs by default' is not OO. However, given that, as has been
pointed out, it is a 'magic' construct (or at least 'next', upon which it
depends, is), and that it works sensibly for all tables, and that it can be
overridden or disabled for specific tables using '__iter', it seems useful
and harmless. However if both these Powerpatches are available, 'pairs by
default' could be optional since anyone that wanted it could implement it
using the '__iter' event in a type metatable for Table type.