for loops

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

for loops

Luiz Henrique de Figueiredo
We'd like your opinion on whether we should add a FOR loop to Lua:

1. Do you miss FOR loops?
2. What syntax would you suggest?

We have been dicussing the matter and have decided that if we're going to add
FOR loops to Lua then it must be a general kind of FOR (as in C), not just the
numeric type (as in FORTRAN, Pascal or Basic).
In other words, we should be able to traverse a table or a linked list using
a FOR.

Now, the real problem is syntax.
After some heated discussion, we think that the syntax below is ok:

   FOR statement1 THEN statement2 WHILE expression DO block END

which is sugar for

   statement1
   WHILE expression DO block; statement2 END

With this FOR you can write:

   for i=1 then i=i+1 while i<=10 do s=s+a[i] end

and also

   for local i,v=next(t,nil) then i,v=next(t,i) while i do process(i,v) end

and also

   for local x=head then x=x.next while x do process(x) end

However, we're not really too happy with this, nor really convinced that Lua
needs a FOR loop.

We'd like your input on this matter.
Thanks.
--
Luiz Henrique de Figueiredo                    email: [hidden email]
TeCGraf-Grupo de Tecnologia em Computacao Grafica, Dep. Informatica, PUC-Rio
Rua Marques de Sao Vicente 225                        voice: +55 21 529-9424
22453-900 Rio de Janeiro, RJ, Brasil                    fax: +55 21 294-8195
--

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Luiz Henrique de Figueiredo-2
>t={1,2,3,'eww'}
>for elt in t do
>	do_whatever(elf)
>end
>
>This is not the most general 'for' you can think of, but this is what I do
>most of the time: go through a table and look at each element. Sure, you
>can do it using next etc, but this would be much less hassle.
>

This will be catered for in 3.1 with a new builtin function 'foreach'.
With this, your example will be written
	foreach(t,do_whatever)
or something like that.
Moreover, 3.1 will bring dynamic function closures so you'll be able to write

	foreach(t,function (x) print(x.name) end)

--lhf

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Alan Watson-2
In reply to this post by Luiz Henrique de Figueiredo
It's true that "for" loops are syntactic sugar, but then if you have
"if" and "goto" so are "while" loops. Syntactic sugar has to be judged
on whether it aids or hinders a human attempting to understand a
program.

On this basis, I don't like general "for" loops. However, I do like
restricted "for" loops as an easily recognizable idiom for simple
loops over a range of integers or the indicies of a table. If the loop
is more complex, I prefer to use an explicit "while" loop as a flag
that I'm going to have to think a little bit more carefully.

If you are going to add "for" loops, then I urge you to restrict
yourself to loops like "for i = 1 to 10 do ... done" and "for i in
table do ... done". I doubt the latter is identical to the proposed
"foreach" function because of scope, although I could be wrong.

"If in doubt, leave it out".

Alan

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Michael Spalinski-2
In reply to this post by Luiz Henrique de Figueiredo
>>>>> "Luiz" == Luiz Henrique de Figueiredo <[hidden email]> writes:

    Luiz> We'd like your opinion on whether we should add a FOR loop to
    Luiz> Lua:

    Luiz> 1. Do you miss FOR loops?  2. What syntax would you suggest?

Yes, I miss for loops. The syntax that I would find most useful is

t={1,2,3,'eww'}
for elt in t do
	do_whatever(elf)
end

This is not the most general 'for' you can think of, but this is what I do
most of the time: go through a table and look at each element. Sure, you
can do it using next etc, but this would be much less hassle.

M.

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Lyn A Headley
In reply to this post by Luiz Henrique de Figueiredo
I am completely in favor of your for loop proposal, its syntax and
semantics.  I miss the loops of C; I think they add convenience
without sacrificing clarity.

-Lyn

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Philippe Goutier
In reply to this post by Luiz Henrique de Figueiredo
I vote for the implementation of a FOR loop.

In the past, I implemented a FOR loop as follows, for an experimental
script language; for examples:

for i = 1, 10, 12, -5+t
...
loop

for str = "a", "b", "ab" + s1, "x" + "z"
...
loop

Philippe

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Carlos Augusto Teixeira Mendes
In reply to this post by Luiz Henrique de Figueiredo
At 15:07 29/10/97 -0200, you wrote:
>We'd like your opinion on whether we should add a FOR loop to Lua:
>
>1. Do you miss FOR loops?

Yes, I do miss for loops, and also miss "break" and "continue" instructions. 

>2. What syntax would you suggest?

Well, thats a matter of taste, but I would suggest:

FOR statement1 WHILE expression THEN statement2 DO block END

In my opinion, it reflects in a better way the real order of execution of
statement1, expression and statement2.

Regards,
Carlos Augusto.



Reply | Threaded
Open this post in threaded view
|

Re: for loops

Roberto Ierusalimschy
In reply to this post by Alan Watson-2
> I doubt the latter is identical to the proposed
> "foreach" function because of scope, although I could be wrong.

  The reason why Lua 3.0 doesn't have nested functions is scope. At one
hand, it is almost useless to be able to write a nested function without
access to local variables of the enclosing environment. On the  other hand,
it is well known the problem of "dangling references" to these variables,
like below:

    function f(x) return function (y) return x+y end end

    a = f(4)
    print(a(5))   -- where/what is "x"??


  In Lua 3.1, we are proposing a solution to this problem which we have
called "upvalues" (don't pay much attention to the name...). An upvalue
is an expression of the form "%name", which is evaluated when a function
is *created*, and not when it is called. "name" can be any variable
visible at the point where the function is created, that is, a local
variable of the enclosing environment or a global variable. With this,
the above example could be written as:

    function f(x) return function (y) return %x+y end end

Now, when "f(4)" is executed, the inner function is created and the "%x" is
evaluated to the constant "4"; so "a" will get a function like
"function (y) return 4+y end", and "a(5)" will give the correct result.
(Notice that if you write "x+y" in the function body you get a
compiler error, since 'x' is out of scope; therefore it is not that
difficult to remember to use the '%'. On the other hand, the '%' reminds
that this is not an usual variable access.)

  Function "foreach" will be pre-defined, but it could be defined in Lua
as well (the pre-defined version is much more efficient):

    function foreach (t, f)
      local i, v = next(t, nil)
      while i do
        local r = f(i, v)
        if r then return r end
        i, v = next(t, i)
      end
      -- return nil
    end

(a similar "foreachvar" will traverse global variables, with "nextvar").

  With those facilities, Lua 3.1 will support code like:

    -- cloning a table 't':
    local new = {}; foreach(t, function (i, v) %new[i] = v end)

    -- searching an index with a given value 'value':
    i = foreach(t, function (i, v) if v == %value then return i end end)
    -- if i==nil then value not found

    -- counting the number of elements in a table:
    count = {n=0}; foreach(t, function() %count.n = %count.n + 1 end)
    -- (notice that upvalues cannot be assigned, so the use of a table
    -- field 'n')

    -- "quick and dirt" print of a table contents:
    foreach(t, print)

  Therefore, we hope that "foreach" will be able to replace most current loops
that use "next". (Nevertheless, we think that *if* Lua gets a "for"
constructor, this constructor should allow the traversal of tables...)


  Obviously, nested functions + upvalues are very useful in many other
uses not related to traversing tables. For instance:

    -- collecting all words in a string:
    local words = {n=0}
    gsub(s, "(%w%w*)", function (w)
                         %words.n=%words.n+1; %words[%words.n] = w;
                       end)

    -- avoiding (accidental) redefinition of pre-defined functions:
    settagmethod(tag(print), "setglobal",
                 function(n) error("cannot redefine function "..n) end)


  Finally, upvalues have other uses independently of nested functions.
For instance, one can redefine a standard function:

print = function (s)
          if strlen(s) > 1000 then error("string too long to print") end
          %print(s)   -- upvalue!
        end

  The "%print" is evaluated when the function is declared, and its value
is then fixed to the old print function. This old function, however, is
not accessible from any other part of the program, since the global name
"print" has been redefined.


-- Roberto

PS: with nested functions, one could "define" for constructors, with
endless variations, like:

   function for (i, e, f)
     while i<e do f(i); i=i+1 end
   end

PS2: we must keep in mind that a "for" construct creates a small
compatibility problem, since "for" will be a reserved word (that's why
we `reuse' the keyword "then" in our proposal...).

Reply | Threaded
Open this post in threaded view
|

RE: for loops

Bret Mogilefsky
In reply to this post by Luiz Henrique de Figueiredo
I too miss break and continue... Also, I think the "FOR" notation below
far beats the proposed one... It makes sense as you read it.

Bret

> -----Original Message-----
> From:	Carlos Augusto Teixeira Mendes [SMTP:[hidden email]]
> Sent:	Thursday, October 30, 1997 4:29 AM
> To:	Bret Mogilefsky
> Subject:	Re: for loops
> 
> At 15:07 29/10/97 -0200, you wrote:
> >We'd like your opinion on whether we should add a FOR loop to Lua:
> >
> >1. Do you miss FOR loops?
> 
> Yes, I do miss for loops, and also miss "break" and "continue"
> instructions. 
> 
> >2. What syntax would you suggest?
> 
> Well, thats a matter of taste, but I would suggest:
> 
> FOR statement1 WHILE expression THEN statement2 DO block END
> 
> In my opinion, it reflects in a better way the real order of execution
> of
> statement1, expression and statement2.
> 
> Regards,
> Carlos Augusto.
> 
> 

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Waldemar Celes-3
> Also, I think the "FOR" notation below
> far beats the proposed one... It makes sense as you read it.

> >
> > Well, thats a matter of taste, but I would suggest:
> >
> > FOR statement1 WHILE  expression THEN statement2 DO block END
> >

I particularly prefer the shorter, although C-like, syntax:

for stat1; exp; stat2 do
 ...
end


-- waldemar

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Pedro Miller Rabinovitch
In reply to this post by Alan Watson-2
On 29 Oct 97 at 15:58, Alan Watson wrote:
> If you are going to add "for" loops, then I urge you to restrict
> yourself to loops like "for i = 1 to 10 do ... done" and "for i in
> table do ... done". 

I agree with Alan. IMHO, for loops in a language like Lua should be 
kept simple. I feel the simple "for i = 1 to 10 do... end" would be 
much more appropriate than a complicated "for-then-while-do-end" 
statement.

Whatever is decided, I feel foreach would be a great advancement, and 
am very happy to hear it shall be predefined in Lua 3.1.

Pedro

----------------------------------
    Pedro  Miller Rabinovitch
    [hidden email]
----------------------------------

What I want is all of the power and none of the
responsibility.
 

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Mark Ian Barlow
In reply to this post by Luiz Henrique de Figueiredo
In message <199710302022.SAA22551@...> [hidden email] writes:
 > On 29 Oct 97 at 15:58, Alan Watson wrote:
 > > If you are going to add "for" loops, then I urge you to restrict
 > > yourself to loops like "for i = 1 to 10 do ... done" and "for i in
 > > table do ... done". 
 > 
 > I agree with Alan. IMHO, for loops in a language like Lua should be 
 > kept simple. I feel the simple "for i = 1 to 10 do... end" would be 
 > much more appropriate than a complicated "for-then-while-do-end" 
 > statement.

This gets my vote too; I want to provide Lua implementations to naive
end-users, the more complex and complete form would, IMHO, merely
confuse them.

--  Mark Ian Barlow                Non-Linear Control Consultants Ltd.
    -----------------------------------------------------------------
    [hidden email]            Voice / Fax: +44 (0)1207 562 154

Reply | Threaded
Open this post in threaded view
|

GC de upvalues

Tomás Guisasola-2
In reply to this post by Roberto Ierusalimschy
	Oi Roberto,

	tudo bom?  Quando voce colocou este exemplo:
> print = function (s)
>           if strlen(s) > 1000 then error("string too long to print") end
>           %print(s)   -- upvalue!
>         end
> 
>   The "%print" is evaluated when the function is declared, and its value
> is then fixed to the old print function. This old function, however, is
> not accessible from any other part of the program, since the global name
> "print" has been redefined.

	fiquei curioso de saber como voces resolvem o problema de coleta
da funcao print (original).

	Abraco,
		Tomas

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Diego Nehab-3
In reply to this post by Pedro Miller Rabinovitch
Alan Watson wrote:

> If you are going to add "for" loops, then I urge you to restrict
> yourself to loops like "for i = 1 to 10 do ... done" and "for i in
> table do ... done".

I also miss for loops, very much. The one who never wrote something like

while i < 10 do
  something(i)
end 

and, for a second or two, wondered why the program was not working can
say for loops have no use. One has always to remenber defining the
counter variable and incrementing it within the while loop, something
obvious with for loops.

Also, I agree with the simple syntax. One would prefer using while loops
then writing all the "for-then-while-do-end" stuff.

I would suggest the counter specified in the for declaration to be
local. That is:

i = 7
for i=10 to 1 do
  something(i)
end
print(i)

should print the value 7, leaving the global i unchanged. That would
avoid a lot of problems of "counter sharing" between loops.

I also miss, even more than for loops, break and continue as in C. I
have already discussed the matter briefly with Roberto and he has some
neat ideas on the subject. Since we are discussing about possibilities
for the next version, why not discuss this also?

Diego Nehab.

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Philippe Goutier
>>I also miss, even more than for loops, break and continue as in C.
>> I have already discussed the matter briefly with Roberto and he has
>> some neat ideas on the subject. Since we are discussing about
>> possibilities for the next version, why not discuss this also?

One suggestion on the subject would be an extension to the C "break": a
statement such as "break all" to exit all imbricated loops in just one
operation.

Philippe

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Russell Y. Webb
In reply to this post by Diego Nehab-3
> I also miss, even more than for loops, break and continue as in C. I
> have already discussed the matter briefly with Roberto and he has some
> neat ideas on the subject. Since we are discussing about possibilities
> for the next version, why not discuss this also?

Break and Continue would be great to have.  What are the neat ideas?

Russ

Reply | Threaded
Open this post in threaded view
|

Re: for loops

David Jeske-2
In reply to this post by Philippe Goutier
On Fri, Oct 31, 1997 at 02:39:56PM -0200, Philippe Goutier wrote:
> >>I also miss, even more than for loops, break and continue as in C.
> >> I have already discussed the matter briefly with Roberto and he has
> >> some neat ideas on the subject. Since we are discussing about
> >> possibilities for the next version, why not discuss this also?

> One suggestion on the subject would be an extension to the C "break": a
> statement such as "break all" to exit all imbricated loops in just one
> operation.

I don't miss break and continue. I find their use ambigiuous, and anything
you can do with them, can be done with standard blocks easily.

I really prefer Java's incarnation of the "break" statement. It's a
combination of the break concept and a "goto". You have to specify a
destination for the break. Unless you use break in only one language and
use it frequently, the location you are going to break to is usually
ambigious IMO. The AT&T phone switch crash which occured several years
back ('89) here in the US was the result of a misinterpreted break
statement.

So, for example:

function a(x,y)
    local i = 0;

    while i < 5 do
       ..stuff..
       if g(i) then
           break exitfn;
       end
       if f(i) then
           while g(i) < 2 do
              ..stuff..
              if z(i) then
                   break exitfn;
              end
           end
       end
    end

  exitfn:
    print("we're done");
    
end


-- 
David Jeske (N9LCA) + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Alan Watson-2
In reply to this post by Luiz Henrique de Figueiredo
> At one
> hand, it is almost useless to be able to write a nested function without
> access to local variables of the enclosing environment. 

Hmm. I'm not so sure. A number of languages allow nested function, but
within nested function it is only possible to access the current
function's locals and globals. This is a very clean and easy to
understand model, and it has been proven to be useful over a time span
that stretches from BCPL to Python.

You can get around some of the restrictions by providing a few more
builtin-looping functions, such as Python's map, filter, and reduce
(see the "Lambda And Functional Programming Tools" section of
http://www.python.org/doc/tut/tut.html).

My reaction to %foo is that on the whole I'd rather have a simpler
language than a more powerful one.

Alan

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Philippe Goutier
>>My reaction to %foo is that on the whole I'd rather have
>> a simpler language than a more powerful one.

Good point of view. That's the current strength of LUA.

Philippe

Reply | Threaded
Open this post in threaded view
|

Re: for loops

Diego Nehab-3
In reply to this post by David Jeske-2
Hi,

David Jeske wrote:
> I don't miss break and continue. I find their use ambigiuous, and anything
> you can do with them, can be done with standard blocks easily.

I agree with the ambiguity of the break statement. And, although I also
agree that it's easy to simulate a break statement with standard blocks,
I still think it's much easier to stop a loop at once with a break
within the loop block. At least when we are sure of where our break
statement will take us to...  

> I really prefer Java's incarnation of the "break" statement. It's a
> combination of the break concept and a "goto". 

This sound's too much like a goto statement. IMHO, it would be cleaner
if we could label a block and then break out of the block - something
like this:

-- finds for the first occurence of an element in a matrix
done: begin
  i = 0
  while i < m do
    j = 0
    while j < n do
      if matrix[i][j] == wanted then
        break done
      end
      j = j + 1
    end
    i = i + 1
  end
end

Dijkstra would like it better, for sure. :-)

PS: This was one of the neat ideas Roberto mentioned to me.

12