On Aug 17, 2014, at 7:10 PM, Coroutines <coroutines@gmail.com> wrote:
On an unrelated note: __pairs and __ipairs are not necessary to be
upstream -- I wish they were so it promotes an interface everyone
knows about, but you can just wrap ipairs() and pairs() of course.
I'm sad to see __ipairs go, I feel like we went back a step.
I’m really not sure where I stand on this whole ipairs() thing. The fact is, the various metamethods being added/extended are moving Lua more and more in the direction of generic programming, which is *probably* good as long as it doesn’t get out of hand (.Net or Java class libraries anyone? <shudders>).
So let’s say you wish to write a generic function that contains generic iteration. What does it look like? Well, you really have to supply two things: the item to iterate and the generator…
function generic_func_that_iterates_A(item, f)
for k, v in f(item) do
— stuff
end
end
This is flexible if the same item may have multiple iterators, but in many cases it’s better if the item carries its own iterator. How does it do that? Using __pairs() of course…
function generic_function_that_iterates_B(item)
for k,v in pairs(item) do
— stuff
end
end
To my mind, this is the real purpose of pairs(); to provide generic iteration for types with metatables. This is more elegant than passing a generator every time. Of course you can have the best of both A and B…
function generic_func_that_iterates_C(item, f)
f = f or pairs
for k, v in f(item) do
— stuff
end
end
But notice this is all about pairs(), not ipairs(). It’s pairs() and __pairs() that provide this generic model to my mind. ipairs() is really just a convenience function, created as an obvious companion to pairs(). After thinking it through I think Roberto and co are right; ipairs() is just a convenience for iterating over the numeric range [1,#t], and nothing else, and has no business having __ipairs() at all; the low-level __len/__index can do all the necessary abstraction.