lua-users home
lua-l archive

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


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.