[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Adding direct enumeration of collections to Lua generic for loops
- From: Jean-Luc Jumpertz <jean-luc@...>
- Date: Tue, 3 Apr 2018 20:17:36 +0200
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
>