List of Closures and traditional for lopp

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

List of Closures and traditional for lopp

Jochen Theodorou
Hi,

while thinking about macros I stubmled about the foor loop again... we have:

for (x in list) {
}

and the traditional version that we don't have is

for (int i=0; i<n; i++) {

}

Now I am thinking that (int i=0; i<n; i++) is quite alien syntax in
Groovy, but why not making it into something useful? how about a list of
closures? so

(int i=0; i<n; i++)

would be equal to

[{int i=0},{i<n},{i++}]

or

[{->int i=0},{->i<n},{->i++}]

that depends on what we want to focus.. anyway, I think this can be
handy if someone has to define more than one short closure. the nice
thing now is, that the for-loop can be seen as:

"for" ("(" in-expression ")" | closure-list-expression) block

and the compiler could take the list and transform it in what is needed
for the for loop. such a list could then contain more than 3 parts, we
soulc form that the middle part is always used for the boolean condition
the parts before for init and the parts later for increment. if the
number of items in the list is even, we could put bigger weight on the
init or increment part... for example (int i=0; long j=1; i<j+1; i*=3)
whould contain two init parts with different types... something that the
classic for loop can not do. At no point would the compiler really
create a closure for the for-loop, but that would be the standard.

I am sure such lists can be used later for more than only the for loop.
Especially in combination with macros or methods taking more than only
one closure...

Of course... to be inline with the for-loop we would have to make a
variable defined in a closure in such a list be available in all other
closures too. that would mean a change to the scoping rules somehow...
while exactly like the classic for-loop. we could even extend the list
idea and allow empty statements described by a special constant Closure
as in {}. Then we could do things like:

list.each (int i=0; it<"foo" && i<10; i++; it+i) {
   println "$i: $it"
}

with

def each (init, cond, incr, ret, body) {
   init()
   for (element in this) {
     if (!cond(it)) break
     body(it)
     incr(it)
   }
   return ret()
}

the scope of i would be the be limited to the closure list and the
closure attached to the method call. I think it is not very easy to
simulate such a closure in groovy suing the current mechanisms and not
get a huge amount of curly braces everywhere. Allowing empty entries
means that we can rewrite that as:

list.each (;it<"foo";;) {
   println "$it"
}

which is the same as above, only that we have no effects in init, incr,
and ret. For example ret could be empty very often. The empty version
comes in handy because we don't have to check for the number of elements
then. if we say the empty closure is always a constant, then we could
check for that constant (or don't sue a constant and isntead use a
method defined on the closure) to skip the execution of that part and
apply default logic.

Thoughts?

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

Martin C. Martin-2
I like the idea of allowing more than 3 clauses.  In "The Evolution of
Lisp," Steele and Gabriel say:

"Arguments over syntax aside, there is something to be said for
recognizing that a loop that steps only one variable is pretty useless,
in *any* programming language.  It is almost always the case that one
variable is used to generate successive values while another is used to
accumulate a result.  If the loop syntax steps only the generating
variable, then the accumulating variable must be stepped "manually" by
using assignment statements ... or some other side effect.  The
multiple-variable do loop reflects and essential symmetry between
generation and accumulation, allowing iteration to be expressed without
explicit side effects:

(defun factorial (n)
   (do ((j n (- j 1)
        (f 1 (* j f)))
     ((= j 0) f)))

"It is indeed not unusual for a do loop of this form to have an empty
body, performing all its real work in the step forms."


That said, I'm worried about declaring a variable in one closure and
using it in another.  That would be a kind of special case behavior for
closures, which would probably confuse new programmers to no ends,
especially since many programmers find closures complicated anyway.

Best,
Martin

Jochen Theodorou wrote:

> Hi,
>
> while thinking about macros I stubmled about the foor loop again... we
> have:
>
> for (x in list) {
> }
>
> and the traditional version that we don't have is
>
> for (int i=0; i<n; i++) {
>
> }
>
> Now I am thinking that (int i=0; i<n; i++) is quite alien syntax in
> Groovy, but why not making it into something useful? how about a list of
> closures? so
>
> (int i=0; i<n; i++)
>
> would be equal to
>
> [{int i=0},{i<n},{i++}]
>
> or
>
> [{->int i=0},{->i<n},{->i++}]
>
> that depends on what we want to focus.. anyway, I think this can be
> handy if someone has to define more than one short closure. the nice
> thing now is, that the for-loop can be seen as:
>
> "for" ("(" in-expression ")" | closure-list-expression) block
>
> and the compiler could take the list and transform it in what is needed
> for the for loop. such a list could then contain more than 3 parts, we
> soulc form that the middle part is always used for the boolean condition
> the parts before for init and the parts later for increment. if the
> number of items in the list is even, we could put bigger weight on the
> init or increment part... for example (int i=0; long j=1; i<j+1; i*=3)
> whould contain two init parts with different types... something that the
> classic for loop can not do. At no point would the compiler really
> create a closure for the for-loop, but that would be the standard.
>
> I am sure such lists can be used later for more than only the for loop.
> Especially in combination with macros or methods taking more than only
> one closure...
>
> Of course... to be inline with the for-loop we would have to make a
> variable defined in a closure in such a list be available in all other
> closures too. that would mean a change to the scoping rules somehow...
> while exactly like the classic for-loop. we could even extend the list
> idea and allow empty statements described by a special constant Closure
> as in {}. Then we could do things like:
>
> list.each (int i=0; it<"foo" && i<10; i++; it+i) {
>   println "$i: $it"
> }
>
> with
>
> def each (init, cond, incr, ret, body) {
>   init()
>   for (element in this) {
>     if (!cond(it)) break
>     body(it)
>     incr(it)
>   }
>   return ret()
> }
>
> the scope of i would be the be limited to the closure list and the
> closure attached to the method call. I think it is not very easy to
> simulate such a closure in groovy suing the current mechanisms and not
> get a huge amount of curly braces everywhere. Allowing empty entries
> means that we can rewrite that as:
>
> list.each (;it<"foo";;) {
>   println "$it"
> }
>
> which is the same as above, only that we have no effects in init, incr,
> and ret. For example ret could be empty very often. The empty version
> comes in handy because we don't have to check for the number of elements
> then. if we say the empty closure is always a constant, then we could
> check for that constant (or don't sue a constant and isntead use a
> method defined on the closure) to skip the execution of that part and
> apply default logic.
>
> Thoughts?
>
> bye blackdrag
>

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

Jochen Theodorou
Martin C. Martin schrieb:
>[...]
> That said, I'm worried about declaring a variable in one closure and
> using it in another.  That would be a kind of special case behavior for
> closures, which would probably confuse new programmers to no ends,
> especially since many programmers find closures complicated anyway.

for (int i=0; i<X; <i++) {System.out.println(i);}

seems not to confuse anyone. All I propose is to make this into a usage
of closures, that's all.. for example think of

myMethod (int i=0; i<X; <i++) {System.out.println(i);}

what exactly is different now? The keyword is no longer there and the
special syntax is gone. So this proposal is not so much about adding new
syntax to groovy, it is about making a special case into a genral case.
I think programers might get confused the first time they see this, but
if they think about it and get the hint to look at the classic for loop,
then they are no longer confused.

I mean... if we say we implement the classic for-loop, and do not the
special scoping for the closure list, then we have to throw the closure
list away completly. It makes no sense to let (int i=0; i<X; <i++)
really behavew different when used for a for loop and then used
somewhere else.

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: List of Closures and traditional for lopp

Dierk König
is
 (int i=0; i<X; <i++)
a typo and you mean
 (int i=0; i<X; i++)
or is there some magic in the < ?

Dierk

> -----Original Message-----
> From: Jochen Theodorou [mailto:[hidden email]]
> Sent: Donnerstag, 1. Februar 2007 14:45
> To: [hidden email]
> Subject: Re: [groovy-jsr] List of Closures and traditional for lopp
>
>
> Martin C. Martin schrieb:
> >[...]
> > That said, I'm worried about declaring a variable in one closure and
> > using it in another.  That would be a kind of special case behavior for
> > closures, which would probably confuse new programmers to no ends,
> > especially since many programmers find closures complicated anyway.
>
> for (int i=0; i<X; <i++) {System.out.println(i);}
>
> seems not to confuse anyone. All I propose is to make this into a usage
> of closures, that's all.. for example think of
>
> myMethod (int i=0; i<X; <i++) {System.out.println(i);}
>
> what exactly is different now? The keyword is no longer there and the
> special syntax is gone. So this proposal is not so much about adding new
> syntax to groovy, it is about making a special case into a genral case.
> I think programers might get confused the first time they see this, but
> if they think about it and get the hint to look at the classic for loop,
> then they are no longer confused.
>
> I mean... if we say we implement the classic for-loop, and do not the
> special scoping for the closure list, then we have to throw the closure
> list away completly. It makes no sense to let (int i=0; i<X; <i++)
> really behavew different when used for a for loop and then used
> somewhere else.
>
> bye blackdrag
>
> --
> Jochen "blackdrag" Theodorou
> Groovy Tech Lead (http://groovy.codehaus.org)
> http://blackdragsview.blogspot.com/
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: List of Closures and traditional for lopp

Dierk König
In reply to this post by Jochen Theodorou
if we go for closures rather than blocks, we have an issue with
return meaning different things in
 for(i in iterable) { return 1 }
and
 for (int i=0; i<X; i++) { return 1}
or not?

ciao
Dierk


> -----Original Message-----
> From: Jochen Theodorou [mailto:[hidden email]]
> Sent: Donnerstag, 1. Februar 2007 14:45
> To: [hidden email]
> Subject: Re: [groovy-jsr] List of Closures and traditional for lopp
>
>
> Martin C. Martin schrieb:
> >[...]
> > That said, I'm worried about declaring a variable in one closure and
> > using it in another.  That would be a kind of special case behavior for
> > closures, which would probably confuse new programmers to no ends,
> > especially since many programmers find closures complicated anyway.
>
> for (int i=0; i<X; <i++) {System.out.println(i);}
>
> seems not to confuse anyone. All I propose is to make this into a usage
> of closures, that's all.. for example think of
>
> myMethod (int i=0; i<X; <i++) {System.out.println(i);}
>
> what exactly is different now? The keyword is no longer there and the
> special syntax is gone. So this proposal is not so much about adding new
> syntax to groovy, it is about making a special case into a genral case.
> I think programers might get confused the first time they see this, but
> if they think about it and get the hint to look at the classic for loop,
> then they are no longer confused.
>
> I mean... if we say we implement the classic for-loop, and do not the
> special scoping for the closure list, then we have to throw the closure
> list away completly. It makes no sense to let (int i=0; i<X; <i++)
> really behavew different when used for a for loop and then used
> somewhere else.
>
> bye blackdrag
>
> --
> Jochen "blackdrag" Theodorou
> Groovy Tech Lead (http://groovy.codehaus.org)
> http://blackdragsview.blogspot.com/
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

Jochen Theodorou
In reply to this post by Dierk König
Dierk Koenig schrieb:
> is
>  (int i=0; i<X; <i++)
> a typo and you mean
>  (int i=0; i<X; i++)
> or is there some magic in the < ?

typo, sorry.

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

Jochen Theodorou
In reply to this post by Dierk König
Dierk Koenig schrieb:
> if we go for closures rather than blocks, we have an issue with
> return meaning different things in
>  for(i in iterable) { return 1 }
> and
>  for (int i=0; i<X; i++) { return 1}
> or not?

I am not proposing to implement for with closures. The compiler would
still create the code. So the problem is reduced to anything we already
have... like:

list.each {return}

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: List of Closures and traditional for lopp

Dierk König
ok, then I'm fine with your proposed solution

+1

Dierk

> -----Original Message-----
> From: Jochen Theodorou [mailto:[hidden email]]
> Sent: Donnerstag, 1. Februar 2007 15:07
> To: [hidden email]
> Subject: Re: [groovy-jsr] List of Closures and traditional for lopp
>
>
> Dierk Koenig schrieb:
> > if we go for closures rather than blocks, we have an issue with
> > return meaning different things in
> >  for(i in iterable) { return 1 }
> > and
> >  for (int i=0; i<X; i++) { return 1}
> > or not?
>
> I am not proposing to implement for with closures. The compiler would
> still create the code. So the problem is reduced to anything we already
> have... like:
>
> list.each {return}
>
> bye blackdrag
>
> --
> Jochen "blackdrag" Theodorou
> Groovy Tech Lead (http://groovy.codehaus.org)
> http://blackdragsview.blogspot.com/
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

tugwilson
In reply to this post by Jochen Theodorou

On 1 Feb 2007, at 13:45, Jochen Theodorou wrote:

> for (int i=0; i<X; <i++) {System.out.println(i);}
>
> seems not to confuse anyone. All I propose is to make this into a  
> usage of closures, that's all.. for example think of


That's because I is declared outside the scope of the block and is  
inherited into the block in the normal way.

In Java and C "(" does not introduce a new scoping context.


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: List of Closures and traditional for lopp

Jochen Theodorou
John Wilson schrieb:

>
> On 1 Feb 2007, at 13:45, Jochen Theodorou wrote:
>
>> for (int i=0; i<X; <i++) {System.out.println(i);}
>>
>> seems not to confuse anyone. All I propose is to make this into a
>> usage of closures, that's all.. for example think of
>
>
> That's because I is declared outside the scope of the block and is
> inherited into the block in the normal way.
>
> In Java and C "(" does not introduce a new scoping context.

right, so there is no problem with the scoping ;) No, ( does really
introduce a new scoping context, because:

for (int i=0; i<X; <i++) {System.out.println(i);}
System.out.println(i);

is illegal, as result of a undeclared i, where

int i =0;
for (i=0; i<X; <i++) {System.out.println(i);}
System.out.println(i);

is allowed. Ok, maybe your "new scoping context" was fixed on the block
rather then the scope we are already in. But even if ( would introduce a
new scoping context and if the block after is automatically part of that
context, would it make a difference? that's the way it is implemented
for the while-statement atm.

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email