lua-users home
lua-l archive

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


Hi,

When enumerating a collection in Lua (i.e. a table or some kind of userdata), a generic for loop is probably the simplest and most straightforward solution.

So most of the time, you write it like:

for key, value in pairs(myCollection) do
  — some stuff
end

Frankly, when you know other languages, the call to ’pairs()’ here looks rather strange and inelegant. What you mean is « iterate in every entry of myCollection and do some stuff », which would probably better be written as:

for key, value in myCollection do
  — some stuff
end

Of course, because you are an experienced Lua programmer, you know what is really going on here. For a table, direct use of the for-in syntax could read something like:

for key, value in next, myCollection, nil do
  — some stuff
end

which, although it carries the full power of iterator functions, is not very readable and exposes to the reader the unneeded complexity of the collection's underlying implementation.

So we are back to calling `pairs()`, which is made compatible with custom types thanks to the "__pairs" metamethod. But again, having to call pairs() is odd, especially if your custom collection type has a single value per entry, or a triplet. :-)

Fore the reasons above, and because my application provides a bridge allowing to transparently mix Lua tables and native iOS collection classes, I started yesterday to investigate if providing direct enumeration of collections in Lua would be complex to implement, and the short answer is that it is finally an easy change.

If you are interested by the code, you can find the diff based on the latest available Lua 5.4 source code here  https://github.com/jlj/lua/commit/d4b680b10cffc048aa85dbd9d4338fa804f79666 (actually I implemented it first in a Lua 5.2 branch, but there is not that much difference between 5,2, 5.3 and 5.4 regarding this part).

In this implementation, if  `collection` is a Lua table or a userdata with the appropriate metamethod, you can now write:

for var1, var2, var3 in collection do
    -- do some stuff
end

Direct for..in enumeration can be customized by defining a "__forgen" (for generator) metamethod that shall return the 3 values needed by the generic for loop: an iterator function, a state, and the initial value of the iterator variable.

If no "__forgen" metamethod is defined and the collection is a Lua table, direct for..in enumeration is equivalent to calling the standard Lua library function pair().

Internally, a new Lua op-code 'OP_TFORPREP' has been added, that replaces the initial JMP instruction when initializing a generic for loop. When executed, this opcode checks for the presence of a "__forgen" metamethod in the loop base object and calls it if present.

I think this is a nice (and fully compatible) addition to Lua, so I decided to share it here.

Lua team, any opinion about this?

Jean-Luc

Attachment: smime.p7s
Description: S/MIME cryptographic signature