D - foreach ( foreach <- D ) { change syntax }
- Jeroen van Bemmel (33/33) Mar 04 2004 Hi Walter,
- Matthias Becker (4/25) Mar 05 2004 in is a keyword.
- J Anderson (36/47) Mar 05 2004 I like this suggestion (I suggested it before). The old syntax could be
- Matthias Becker (1/28) Mar 05 2004 Have you read my proposal about adding "let"?
- J Anderson (6/47) Mar 05 2004 Yeah, but it was a while back (and I couldn't find the original
-
Ben Hinkle
(60/60)
Mar 05 2004
"Jeroen van Bemmel"
wrote in message - Matthias Becker (15/60) Mar 05 2004 Why foreach at all?
- J Anderson (4/8) Mar 05 2004 Having foreach instead of for, prevents syntax errors.
- Jeroen van Bemmel (24/69) Mar 08 2004 But that's just my point: they are not completely parallel.
- Jeroen van Bemmel (14/24) Mar 08 2004 Sorry, this was before I actually read the manual... It seems that for
- C. Sauls (8/12) Mar 07 2004 *response from D* "No I don't... I mean sure, you want an integral, but
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
Mar 04 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.
Mar 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/
Mar 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"?
Mar 05 2004
Matthias Becker wrote: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/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"?
Mar 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 | |
Mar 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();
Mar 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 isHaving foreach instead of for, prevents syntax errors. -- -Anderson: http://badmama.com.au/~anderson/
Mar 05 2004
much.| 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 tooSeems| 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.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 splicinglike 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 isI agree with J Anderson, it's not exactly the same so don't use the same syntaxshould| 2) The type declaration | The type declaration in the foreach syntax is redundant, since itshould be| match the type of elements in the collection. I think the compilercollection| able to determine this somehow (this would require new syntax forYes, 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| 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 aboutwillvoid 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 otherwiseresult 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();
Mar 08 2004
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 typeSorry, this was before I actually read the manual... It seems that for specific collections (the ones supporting indices) you can use at most 2 variables, 1 receiving the index and the other the value / reference of the items in the collection. At first sight this feature hurts my eyes while reading about it. Too many exceptional cases for my taste As long as we're doing things implicitly, why not have something like this: foreach<c> : "a_string" { printf( "%d: '%c'"), c.index. c ); } where 'c.index' is defined for collections supporting indices (and could be computed for the ones that don't) After all, 'foreach' could be considered a template where all that's missing is the name of the iteration variable...
Mar 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
Mar 07 2004