lua-users home
lua-l archive

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


Oops, sorry, wrong link to the code, the actual commit is https://github.com/jlj/lua/commit/688bebeb611c3d317acddb47e280c32e59280614

> Le 3 avr. 2018 à 20:15, Jean-Luc Jumpertz <jean-luc@celedev.eu> a écrit :
> 
> 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
>