lua-users home
lua-l archive

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

On Wed, Dec 31, 2008 at 5:17 PM, Benjamin Tolputt wrote:
> On 12/31/08, Lee Hickey wrote:
> I don't understand why the '#' syntax does not use the __len metamethod

See concerning __len, __pairs,
and __ipairs.

Note that in contrast to the proposed __len metamethod for tables, the
proposed __pairs/__ipairs metamethods are not integral to the Lua VM.
They are used only conventionally by the pairs/ipairs iterator
functions.  You can alternately use your own iterator functions, even
ones that honor __pairs/__ipairs, or redefine pairs/ipairs from Lua.

I'm not certain if next and lua_next are in any way affected though in
5.2 (perhaps not).

>From the blog:
> The problem is that standard functions like table.insert or
> table.remove do raw accesses to the table.

True, the table.* functions use raw gets/sets.  I think these would be
better named array.* since they are mostly, though not exclusively,
designed for "raw arrays"--i.e. tables containing positive integer
keys and lacking overridden operators defined in a metatable. This is
in contrast to metatable-backed tables or userdata used to represent
interfaces to abstract data types with overridden operators.  A
typical example of raw arrays is for efficient /internal/
implementations--an algorithm inside a function or internal storage
for a data type.

Therefore, I question why table.* functions should honor metamethods.
If you want your ADT to have an "insert" operation, you could
implement it as a dynamically bound method:

   obj:insert(pos, value)

For a raw array, you can do setmetatable({}, {__index=table}) to allow
consistent calling.  However, that calling convention is not supported
for raw arrays lacking a metatable and not containing 'insert' as a
raw key--hence, the various table.* functions as non-members.

Another solution is to implement your own set of table.* like
functions that honor some more fundamental array-like ADT interface:

  myarray.insert(obj, pos, value)
  -- only calls public methods (including [] operator) on obj

For debugging it may even be useful to redefine table = myarray.

Along similar lines, the string.* functions only operate on raw Lua
strings.  You cannot define your own custom string type (using tables
or userdata) and pass it to the string.* functions.  You could,
however, in the same manner, use dynamic binding (e.g. s:find(...)) or
reimplement your own string.* functions to operate on a more abstract
string interface (see ).
We have a similar situation for io.* functions.  (Related discussion: .)