ipairs, for a while, was going to be removed from Lua 5.2 . Or there were rumors about it; I didn't pay too much attention to them. At the end, it was kept in Lua, and I think that was a good decision.
tdc5013 wrote:So if ipairs basically does the same job as a basic for loop, why does it exist? Is there a specific function it can apply to, where you'd need to specifically use it, rather than something like the for loop you illustrated?
That's a very good question. I thought about it myself, and found a possible explanation.
First of all, ipairs is not
exactly like pairs. pairs doesn't give any guarantee about the order in which the elements of the array are parsed. I think right now, it *does* respect the numerical order, but that's an implementation detail; other implementations, like LuaJIT or Lua 5.3, could change the implementation so that it didn't respect the order, and that would still be compatible with the Lua spec. My point is, you can't make the assumption in your code when using pairs.
The obvious conclusion to all this is - ok, I'll use a numeric for then. So, why do I need ipairs?
Well, the answer is, yeah, use a numeric for when you can. But in some occasions you can't. Sometimes you just need an iterator function.
Consider the typical copy function:
Code: Select all
function copy(tbl)
local result = {}
for k,v in pairs(tbl) result[k] = v end
return result
end
As far as I know, in the standard 5.1 Lua, this function works with both hash-like tables and array-like tables - but this is an implementation detail; pairs is not guaranteed to follow the numerical order in keys, so in the next version of Lua, or in an alternative implementation, it might copy the keys in a different order (so it would not generate an array, but a hash). Without ipairs, you would end up needing two different implementations; one for copying arrays, using the numeric for, which is guaranteed to follow the numeric keys, and another one for the rest.
But with ipairs, you can do this:
Code: Select all
function copy(tbl, iterator)
iterator = iterator or pairs
local result = {}
for k,v in iterator(tbl) result[k] = v end
return result
end
This version of the function accepts a second (optional) parameter called "iterator". By default, it is pairs. But you can set it to ipairs if you want:
Code: Select all
t1 = {1,2,3}
t2 = copy(t1, ipairs)
So, you can get numerical order, if you need it.
Setting the iterator as an optional parameter has another benefit: you can example, create an iterator function that returns only the even members of the array - or the members of the array in reverse order. Or only the members of a hash whose key starts with "a". And the copy function will work with those, too:
Code: Select all
t3 = copy(t1, evenpairs)
t4 = copy(t1, reverseipairs)
t5 = copy(t1, keystartpairs("a"))
So, this is the reason I imagine ipairs exist: When you are developing a function that parses tables, sometimes,you want to let the users of that function specify how they want to parse a table - like with the iterator parameter. And on the other hand, when you are using that function, you may want to have the guarantee that the numeric values are parsed in order. Granted - very rare case. But possible.
At least that is my opinion. I haven't checked that on the Lua mailing list or anything.