lua-users home
lua-l archive

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

On 1 Jan 2008, at 16:50, Peter Cawley wrote:

AFAICS, the numeric for is simply a syntactical convenience which allows
loops like this:
The generic for loop is also a syntactical convenience (although
generic for and numeric for both use dedicated opcodes in the VM
rather than the ones used by while/until loops).
I'm not sure why you'd want or need to implement a numeric for using a generic for (as you seem to want to do), though you can if you wish (just
not in the way you propose).
It simply seems inconsistent that a numeric for loop is the only place
in Lua where a function call or vararg at the end of the expression
list is not expanded to the number of returned results;
a,b = f()
t = {a, b, f()}
f(a, b, f())
for a,b in f() do
for a = b, f() do -- The second return value of f(), if there is one,
is discarded

There is another case to be made for allowing "for i = f() do ... end", I think.

The issue it could address is indexing ranges, i.e. the "0..N-1" vs "1..N" discussion. I got the idea from watching Guy Steele's presentation on a language called "Fortress":
It's a (great) 1-hour presentation, at one point he goes into 0-based vs 1-based indexing, one of the stumbling blocks when dealing with both Fortran- and C-like languages.

Bear with me, please:

- suppose Lua were to be extended with a new monadic operator, say ":expr"
- suppose also there were a new slot in metatables, say "__range"
- the __range entry is a function, which gets called as range(obj,iter)
- two usage patterns:
	for i = :object do ... end
	for i in :object do ... end
- range gets called with the object, and iter true with "=", false with "in" - range returns either 2 from & to values, used for closed interval iteration
- or it returns a state & generator, probably much like pairs/ipairs/etc

The idea being that items which are collections of some sort (including userdata that wants to behave as such) can return the info needed to efficiently iterate over all elements.

With userdata which expects 0-based indexing in its __index method, ":ud" could return (0,#ud-1), whereas with tables ":t" would return (1,#t). It is up to each object type to return the proper bounds, i.e. 0- or 1-based becomes a property of the container, the language no longer needs to care. Then again, since range() returns two values, you could also explicitly grab the boundaries through "a,b=:obj" (hence "a=:obj" gets you the lower bound all by itself).

There may be ways to generalize/simplify this idea. I really haven't figured out how it relates to pairs/ipairs, nor whether there are good choices for ":x" when x is some other type. If it's not feasible at all for some reason, please shoot this down asap!

With such a range operator, one could then use "for i=:t do ..." to iterate over the array part of a table, and "for k in :t do ..." to iterate over the associative part of a table.

To summarize, the above presents two ideas:

1) create a ":obj" range operator which returns 2 values
2) extend the "for i= ... do" notation to support "for i=f() do"

Idea #1 is not crucial, but could be a nice convenience (just as len() became "#").

Could someone well-versed in Lua's intricate details please fill in the gaps, or suggest better solutions, or else expose some fatal flaw in all of this?


PS. I do *not* want to open the 0- vs 1-based can of worms - I am simply looking for ways to deal with situations where the mix of both is unavoidable.