lua-users home
lua-l archive

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


Here is the sort of example I would probably point to in this argument:

	for n in numbers( 1, 1000 ):filter( isprime ):map( square ) do
		-- do something with the square of a prime between 1 and 1000
	end

Basically, we want to build up the final iterator and then execute it.

Or:

	for name in DBTable[ 'Customers' ]:where( 'Age', lessThan, 50 ):select( 'Name' ) do
		-- database extraction
	end

All of these can be handled by tacking an :iter() onto the end and if this is too much one could use the __call metamethod but that means that you need a couple of essentially magical characters at the end and you would be better off with :iter() for clarity. Or the individual stages could return iterator function objects (e.g., tables with a __call metamethod), but that makes the actual iteration slower since we have to go through metamethod processing on each iteration.

The other approach I've considered for making the above "natural" involves adding a pipe operator:

	for n in numbers( 1, 1000 ) >> filter( isprime ) >> map( square ) do
		-- do something with the square of a prime between 1 and 1000
	end

	for name in DBTable[ 'Customers' ] >> where( 'Age', lessThan, 50 ) >> select( 'Name' ) do
		-- database extraction
	end

This case is more composable in that it assumes that we may be passing along multiple values from step to step. It is just syntactic sugar for:

	for n in map( square )( filter( isprime )( numbers( 1, 1000 ) ) ) do
		-- do something with the square of a prime between 1 and 1000
	end

	for name in select( 'Name' )( where( 'Age', lessThan, 50 )( DBTable[ 'Customers' ]  ) ) do
		-- database extraction
	end

(Getting the parentheses right in those de-sugared versions took careful attention.)

Now, if you made me choose between pipe sugar and __iter, I don't know which way I would go.

Mark

P.S. This sort of sequence is one of the places where it would have been really nice if the end of an iteration were signaled by returning nothing rather than by returning nil. There could be map operations, for example, that result in nil where we don't want to actually terminate the iteration.