Jump to page: 1 2
Thread overview
foreach ( foreach <- D ) { change syntax }
Mar 05, 2004
Jeroen van Bemmel
Mar 05, 2004
Matthias Becker
Mar 05, 2004
J Anderson
Mar 05, 2004
Matthias Becker
Mar 05, 2004
J Anderson
Mar 05, 2004
Ben Hinkle
Mar 05, 2004
Matthias Becker
Mar 05, 2004
J Anderson
Mar 08, 2004
Jeroen van Bemmel
Mar 08, 2004
Jeroen van Bemmel
Mar 08, 2004
C. Sauls
March 05, 2004
Hi Walter,

I finally had the time to read your (and Matt's) article in DDJ on D's
foreach construct. I think it's well-written. I have three suggestions for
even more improvement (in my opinion) of the construct:

1) The syntax
Current syntax is "foreach( uint v; aa ) { ... }" (from the article), ie
first element is a variable declaration and the second is a variable
denoting some collection. My remark may be an itty bitty detail, but I don't
like the ';' in this. Normally ';' is used as statement separator, and in C
the for ( x ; y ; z ) syntax closely related to the notion that x,y,z are
statements that are put in a particular order (it's syntactic sugar for " x
; while (y) { .... z }"). "uint v" may be a statement (variable
declaration), but 'aa' isn't, at least not in itself. The semantics are that
'v' comes from the elements in 'aa', and I think this should be reflected in
the syntax.

Possible alternatives:
foreach( uint v from aa ) { ... }
foreach( uint v in aa ) { ... }
foreach( uint v <- aa ) { ... }
foreach( uint v : aa ) { ... }

"from" and "in" would mean additional keywords, which I don't like too much. My personal preference is the last one using ':'

2) The type declaration
The type declaration in the foreach syntax is redundant, since it should
match the type of elements in the collection. I think the compiler should be
able to determine this somehow (this would require new syntax for collection
classes, similar to templates). Rather similar to the new type safe
collections in Java, which I like too.

3) The 'opApply' convention
Why not use 'foreach' as the method name? This reflects the context in which
the method is invoked, and also allows syntax such as "aa.foreach( f )"
which IMO is slightly more readable than "aa.opApply( f )"

JvB


March 05, 2004
>1) The syntax
>Current syntax is "foreach( uint v; aa ) { ... }" (from the article), ie
>first element is a variable declaration and the second is a variable
>denoting some collection. My remark may be an itty bitty detail, but I don't
>like the ';' in this. Normally ';' is used as statement separator, and in C
>the for ( x ; y ; z ) syntax closely related to the notion that x,y,z are
>statements that are put in a particular order (it's syntactic sugar for " x
>; while (y) { .... z }"). "uint v" may be a statement (variable
>declaration), but 'aa' isn't, at least not in itself. The semantics are that
>'v' comes from the elements in 'aa', and I think this should be reflected in
>the syntax.
>
>Possible alternatives:
>foreach( uint v from aa ) { ... }
>foreach( uint v in aa ) { ... }
>foreach( uint v <- aa ) { ... }
>foreach( uint v : aa ) { ... }
>
>"from" and "in" would mean additional keywords, which I don't like too much. My personal preference is the last one using ':'

in is a keyword.

And in 'for ( x ; y ; z )' y is a statement? Nope. y is just like aa in your
foreach example.


>2) The type declaration
>The type declaration in the foreach syntax is redundant, since it should
>match the type of elements in the collection.

You forgot to explain, why it has to match. IMHO it doesn't have to.


March 05, 2004
Jeroen van Bemmel wrote:

>Hi Walter,
>
>I finally had the time to read your (and Matt's) article in DDJ on D's
>foreach construct. I think it's well-written. I have three suggestions for
>even more improvement (in my opinion) of the construct:
>
>
>2) The type declaration
>The type declaration in the foreach syntax is redundant, since it should
>match the type of elements in the collection. I think the compiler should be
>able to determine this somehow (this would require new syntax for collection
>classes, similar to templates). Rather similar to the new type safe
>collections in Java, which I like too.
>  
>
I like this suggestion (I suggested it before). The old syntax could be kept for situations where you need to spell out which opApply to use, but in other cases it's redundant.  Almost everytime I use a foreach, I find myself having to look up the type.

foreach (n; array)
{}

Would be a lot easier to remember. One thing I like about D is that in may cases it has removed the redundancies that exist in C++.  The think I don't like is that D has brought in new redundancies by not having automatic type deduction.  If automatic type deduction is so difficult to implement right, why can't we have a reduced-automatic type deduction.  ie

template Max(T)
{
  T Max(T a, T b) { }
} 

Instead of:
Max!(int).Max(a,b);

use:
Max!!(a,b);

would be equivalent to:
Max!(typeof(a))(a,b);

Note that there would two types, then the order of the would be important. ie

template Foo(T, C)
{
  void Foo(T a, C b) { }
}

Foo!!(a, b);

Equivalent to:
Foo!(typeof(a), typeof(b)).Foo(a,b);

Anything difficult and the compiler could spit at the coder asking for an explicit definition.

-- 
-Anderson: http://badmama.com.au/~anderson/
March 05, 2004
>One thing I like about D is that in may cases it has removed the redundancies that exist in C++.  The think I don't like is that D has brought in new redundancies by not having automatic type deduction.  If automatic type deduction is so difficult to implement right, why can't we have a reduced-automatic type deduction.  ie
>
>template Max(T)
>{
>   T Max(T a, T b) { }
>}
>
>Instead of:
>Max!(int).Max(a,b);
>
>use:
>Max!!(a,b);
>
>would be equivalent to:
>Max!(typeof(a))(a,b);
>
>Note that there would two types, then the order of the would be important. ie
>
>template Foo(T, C)
>{
>   void Foo(T a, C b) { }
>}
>
>Foo!!(a, b);
>
>Equivalent to:
>Foo!(typeof(a), typeof(b)).Foo(a,b);
>
>Anything difficult and the compiler could spit at the coder asking for an explicit definition.
>

Have you read my proposal about adding "let"?


March 05, 2004
Matthias Becker wrote:

>>One thing I like about D is that in may cases it has removed the redundancies that exist in C++.  The think I don't like is that D has brought in new redundancies by not having automatic type deduction.  If automatic type deduction is so difficult to implement right, why can't we have a reduced-automatic type deduction.  ie
>>
>>template Max(T)
>>{
>>  T Max(T a, T b) { }
>>} 
>>
>>Instead of:
>>Max!(int).Max(a,b);
>>
>>use:
>>Max!!(a,b);
>>
>>would be equivalent to:
>>Max!(typeof(a))(a,b);
>>
>>Note that there would two types, then the order of the would be important. ie
>>
>>template Foo(T, C)
>>{
>>  void Foo(T a, C b) { }
>>}
>>
>>Foo!!(a, b);
>>
>>Equivalent to:
>>Foo!(typeof(a), typeof(b)).Foo(a,b);
>>
>>Anything difficult and the compiler could spit at the coder asking for an explicit definition.
>>
>>    
>>
>
>Have you read my proposal about adding "let"?
>
>  
>
Yeah, but it was a while back (and I couldn't find the original suggestion).   I'm not sure if I liked it, didn't like it or didn't understand your proposal.

-- 
-Anderson: http://badmama.com.au/~anderson/
March 05, 2004
"Jeroen van Bemmel" <someone@somewhere.com> wrote in message
news:c2989f$6a6$1@digitaldaemon.com...
| Hi Walter,
|
| I finally had the time to read your (and Matt's) article in DDJ on D's
| foreach construct. I think it's well-written. I have three suggestions for
| even more improvement (in my opinion) of the construct:
|
| 1) The syntax
| Current syntax is "foreach( uint v; aa ) { ... }" (from the article), ie
| first element is a variable declaration and the second is a variable
| denoting some collection. My remark may be an itty bitty detail, but I don't
| like the ';' in this. Normally ';' is used as statement separator, and in C
| the for ( x ; y ; z ) syntax closely related to the notion that x,y,z are
| statements that are put in a particular order (it's syntactic sugar for " x
| ; while (y) { .... z }"). "uint v" may be a statement (variable
| declaration), but 'aa' isn't, at least not in itself. The semantics are that
| 'v' comes from the elements in 'aa', and I think this should be reflected in
| the syntax.
|
| Possible alternatives:
| foreach( uint v from aa ) { ... }
| foreach( uint v in aa ) { ... }
| foreach( uint v <- aa ) { ... }
| foreach( uint v : aa ) { ... }
|
| "from" and "in" would mean additional keywords, which I don't like too much.
| My personal preference is the last one using ':'

The "foreach" syntax should parallel the "for" syntax:
 foreach(declaration-list ; expression) body
 for(declaration-list ; expression ; expression) body
The declaration-list is a comma separated list of looping variables. Seems
like a pretty natural extension of the "for" syntax.

| 2) The type declaration
| The type declaration in the foreach syntax is redundant, since it should
| match the type of elements in the collection. I think the compiler should be
| able to determine this somehow (this would require new syntax for collection
| classes, similar to templates). Rather similar to the new type safe
| collections in Java, which I like too.

Might be nice but if it is added here it would seem odd that foreach is
the only place declaration types get inferred. What about
void foo()
{
   x=1; // c'mon, D, you know what type I want ;-)
}
And someone else mentioned template instantiation. There's a can of worms
in them thar hills.

| 3) The 'opApply' convention
| Why not use 'foreach' as the method name? This reflects the context in which
| the method is invoked, and also allows syntax such as "aa.foreach( f )"
| which IMO is slightly more readable than "aa.opApply( f )"

That sounds very reasonable to me. Another problem I have with opApply is that since overloading is fairly weak in D that an opApply meant for foreach could interfere with an opApply meant for ... opApply and result in casts when they shouldn't be needed. One problem with "foreach" is that it is a keyword and so maybe something like "foreachApply" would be better.

|
| JvB
|
|


March 05, 2004
>| Hi Walter,
>|
>| I finally had the time to read your (and Matt's) article in DDJ on D's
>| foreach construct. I think it's well-written. I have three suggestions for
>| even more improvement (in my opinion) of the construct:
>|
>| 1) The syntax
>| Current syntax is "foreach( uint v; aa ) { ... }" (from the article), ie
>| first element is a variable declaration and the second is a variable
>| denoting some collection. My remark may be an itty bitty detail, but I don't
>| like the ';' in this. Normally ';' is used as statement separator, and in C
>| the for ( x ; y ; z ) syntax closely related to the notion that x,y,z are
>| statements that are put in a particular order (it's syntactic sugar for " x
>| ; while (y) { .... z }"). "uint v" may be a statement (variable
>| declaration), but 'aa' isn't, at least not in itself. The semantics are that
>| 'v' comes from the elements in 'aa', and I think this should be reflected in
>| the syntax.
>|
>| Possible alternatives:
>| foreach( uint v from aa ) { ... }
>| foreach( uint v in aa ) { ... }
>| foreach( uint v <- aa ) { ... }
>| foreach( uint v : aa ) { ... }
>|
>| "from" and "in" would mean additional keywords, which I don't like too much.
>| My personal preference is the last one using ':'
>
>The "foreach" syntax should parallel the "for" syntax:
> foreach(declaration-list ; expression) body
> for(declaration-list ; expression ; expression) body
>The declaration-list is a comma separated list of looping variables. Seems like a pretty natural extension of the "for" syntax.

Why foreach at all?

for (declaration-list; expression) body // like foreach before
for(declaration-list ; expression ; expression) body // stays as is


>| 2) The type declaration
>| The type declaration in the foreach syntax is redundant, since it should
>| match the type of elements in the collection. I think the compiler should be
>| able to determine this somehow (this would require new syntax for collection
>| classes, similar to templates). Rather similar to the new type safe
>| collections in Java, which I like too.
>
>Might be nice but if it is added here it would seem odd that foreach is
>the only place declaration types get inferred. What about
>void foo()
>{
>   x=1; // c'mon, D, you know what type I want ;-)
>}
>And someone else mentioned template instantiation. There's a can of worms
>in them thar hills.
>

That's why I proposed let a while ago.

void foo()
{
let x=1;
}

Well, it was intended to be used in some template-code, as you otherwise will result in code like

typeof(a*b) c = a*b;

which is pretty redundant. But I like it in a VERY common case:

let x = new SomeClassName();

instead of

SomeClassName x = new SomeClassName();


March 05, 2004
Matthias Becker wrote:

>Why foreach at all?
>
>for (declaration-list; expression) body // like foreach before
>for(declaration-list ; expression ; expression) body // stays as is
>  
>
Having foreach instead of for, prevents syntax errors.

-- 
-Anderson: http://badmama.com.au/~anderson/
March 08, 2004
> void foo()
> {
>    x=1; // c'mon, D, you know what type I want ;-)
> }

*response from D* "No I don't... I mean sure, you want an integral, but a s a byte, ubyte, short, ushort, int, uint, long, ulong, cent, ucent, or what?"

Hmm.. no, I think I'd just assume have to tell it.  Its not like it takes long to type 'int'.  As for the type being given for the foreach parameter, what if I have multiple types I can iterate with?

-C. Sauls
-Invironz
March 08, 2004
> >| Possible alternatives:
> >| foreach( uint v from aa ) { ... }
> >| foreach( uint v in aa ) { ... }
> >| foreach( uint v <- aa ) { ... }
> >| foreach( uint v : aa ) { ... }
> >|
> >| "from" and "in" would mean additional keywords, which I don't like too
much.
> >| My personal preference is the last one using ':'
> >
> >The "foreach" syntax should parallel the "for" syntax:
> > foreach(declaration-list ; expression) body
> > for(declaration-list ; expression ; expression) body
> >The declaration-list is a comma separated list of looping variables.
Seems
> >like a pretty natural extension of the "for" syntax.

But that's just my point: they are not completely parallel. 'declaration-list' can only be 1 variable in foreach, and 'expression' denotes neither a termination conditional expression nor the expression calculated for the next loop. The syntax should be restricted to (as it is currently implemented):

foreach( <type-name> <variable> ; <expression> )

So all of the following are wrong (these could be test cases...):

foreach( int a,b; as ) { ... }     // syntax error
foreach( int a; 1 ) { ... }         // semantic error: '1' is not a
collection type

Now that I think about it, how about allowing "foreach( int a : 1..10 ) { ... }" // a..b denotes the sequence of integers from a to b, inclusive, as used in splicing

>
> Why foreach at all?
>
> for (declaration-list; expression) body // like foreach before
> for(declaration-list ; expression ; expression) body // stays as is
>

I agree with J Anderson, it's not exactly the same so don't use the same syntax

>
> >| 2) The type declaration
> >| The type declaration in the foreach syntax is redundant, since it
should
> >| match the type of elements in the collection. I think the compiler
should be
> >| able to determine this somehow (this would require new syntax for
collection
> >| classes, similar to templates). Rather similar to the new type safe | collections in Java, which I like too.
> >
> >Might be nice but if it is added here it would seem odd that foreach is the only place declaration types get inferred. What about

Yes, I know there's lots of other places where types might be inferred. But since 'foreach' already pretends to be a syntactic simplification of a common construct, if anywhere it should be applied there


> >void foo()
> >{
> >   x=1; // c'mon, D, you know what type I want ;-)
> >}
> >And someone else mentioned template instantiation. There's a can of worms
> >in them thar hills.
> >
>
> That's why I proposed let a while ago.
>
> void foo()
> {
> let x=1;
> }
>
> Well, it was intended to be used in some template-code, as you otherwise
will
> result in code like
>
> typeof(a*b) c = a*b;
>
> which is pretty redundant. But I like it in a VERY common case:
>
> let x = new SomeClassName();
>
> instead of
>
> SomeClassName x = new SomeClassName();
>
>


« First   ‹ Prev
1 2