[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Why does numeric for loop not accept an explist?
- From: Jean-Claude Wippler <jcw@...>
- Date: Thu, 17 Jan 2008 22:27:27 +0100
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":
http://www.infoq.com/presentations/fortress-steele
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?
-jcw
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.