[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: what to make of this fellow named __ipairs?
- From: Tony Finch <dot@...>
- Date: Thu, 27 Jan 2011 14:43:45 +0000
On Thu, 27 Jan 2011, David Manura wrote:
>
> A reason we write `ipairs(t)` in the first place is that it's not
> always suitable *in general* to make it a method, `t:ipairs()`, as we
> might do in other languages. In Lua, `t:ipairs`'s existence implies
> `t.ipairs ~= nil` and `t["ipairs"] ~= nil`. Therefore, we make it
> instead a *meta*-method `__ipairs`, which `ipairs` uses to achieve a
> polymorphism similar to a method call. IMO, maybe what we need, more
> generally, is a more convenient notation to call metamethods, as
> opposed to `for k,v in getmetatable(o).__pairs(o) do ...`. Most of
> the time, however, it is just fine to expose the iterator through a
> regular method, conveniently attached to the object, so we have
> `o:iter()` for some custom object `o`. Also, in Lua you can always do
> things like `local ipairs = myipairs; for i,v in ipairs(t) do ...`.
One of the significant oddities in Lua is the distinction between methods
called using the : operator and metamethods called by the language runtime
and some library functions. It is a scruffy mixture of the prototype and
class styles of OOP. David's observations about __ipairs are a good
example of the untidyness.
I think the language would be neater if the method / metamethod
distinction could be reduced or removed. It can be done reasonably nicely,
I think, in a way that supports prototype-style and class-style OOP.
However I don't think it can keep backwards compatibility without
sacrificing efficiency. The key change is a version of the old idea of
making the lookup algorithm for : different from . which allows more
natural support for class-style OOP by making it easy to separate instance
variables from methods.
Method calls on tables without metatables work as at present. If the table
has a metatable the method is looked up in the metatable (instead of the
table itself). If that fails the lookup falls back to a __method
metamethod analogous to the __index metamethod.
For prototype-style OOP,
function new(prototype)
local t = { __index = prototype, __method = prototype }
return setmetatable(t,t)
end
For class-style OOP,
MyClass = { --[[ methods ]] }
function new(class)
return setmetatable({}, class)
end
You get roughly the existing Lua behaviour with
local t = { .... }
local mt = { __method = t, .... }
setmetatable(t, mt)
except that there's no fallback through __index and unknown methods cause
an loop exception instead of an attempt to call nil. Perhaps this setup
could be special-cased to index the table in the current manner... I tend
to think that these caveats are a result of Lua's current semantics being
weird :-)
I note that making methods and metamethods more similar is likely to lead
to Python-style underscore-heavy __magic__ methods, though in Lua they
are asymmetrically __magic.
Tony.
--
f.anthony.n.finch <dot@dotat.at> http://dotat.at/
HUMBER THAMES DOVER WIGHT PORTLAND: NORTH BACKING WEST OR NORTHWEST, 5 TO 7,
DECREASING 4 OR 5, OCCASIONALLY 6 LATER IN HUMBER AND THAMES. MODERATE OR
ROUGH. RAIN THEN FAIR. GOOD.