lua-users home
lua-l archive

Re: what to make of this fellow named __ipairs?

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


On 2011年1月27日, 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.

AltStyle によって変換されたページ (->オリジナル) /