www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Should the comma operator be removed in D2?

reply Justin Johansson <no spam.com> writes:
Mentioned in the switch case statements thread, this probably should be 
a separate discussion thread.

Is the comma operator "another piece of C cruft" that needs to be 
removed from D(2)?


grauzone wrote:
 Justin Johansson wrote:
 bearophile wrote:
 What's bad about forcing people to write:
 case A, B, C:

 Instead of:
 case A:
 case B:
 case C:
 ?

 Bye,
 bearophile

I don't know about "forcing people" to write such but perhaps it could be an "option for people" :-) Actually I quite like the brevity you propose but would it be a challenge for the comma operator? While ago, I got D multi-dimensional array syntax messed up and declared such an animal as int[3,4,5] which effectively ended up declaring the beast as int[5].

The comma operator is another piece of C cruft that needs to go.
 Cheers Justin


Nov 16 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Justin Johansson (no spam.com)'s article
 Mentioned in the switch case statements thread, this probably should be
 a separate discussion thread.
 Is the comma operator "another piece of C cruft" that needs to be
 removed from D(2)?
 grauzone wrote:
  > Justin Johansson wrote:
  >> bearophile wrote:
  >>> What's bad about forcing people to write:
  >>> case A, B, C:
  >>>
  >>> Instead of:
  >>> case A:
  >>> case B:
  >>> case C:
  >>> ?
  >>>
  >>> Bye,
  >>> bearophile
  >>
  >> I don't know about "forcing people" to write such but perhaps it could
  >> be an "option for people" :-)
  >>
  >> Actually I quite like the brevity you propose but would it be a
  >> challenge for the comma operator?
  >>
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.
Nov 16 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
dsimcha wrote:

 == Quote from Justin Johansson (no spam.com)'s article
 Mentioned in the switch case statements thread, this probably should be
 a separate discussion thread.
 Is the comma operator "another piece of C cruft" that needs to be
 removed from D(2)?
 grauzone wrote:
  > Justin Johansson wrote:
  >> bearophile wrote:
  >>> What's bad about forcing people to write:
  >>> case A, B, C:
  >>>
  >>> Instead of:
  >>> case A:
  >>> case B:
  >>> case C:
  >>> ?
  >>>
  >>> Bye,
  >>> bearophile
  >>
  >> I don't know about "forcing people" to write such but perhaps it
  >> could be an "option for people" :-)
  >>
  >> Actually I quite like the brevity you propose but would it be a
  >> challenge for the comma operator?
  >>
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.

It is very simple, evaluates the expression before the comma and after the comma. The result is the value of the expression after the comma. int a = 1; int b = --a, ++a; assert(b == 1); assert(a == 1);
Nov 16 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Lutger (lutger.blijdestijn gmail.com)'s article
 dsimcha wrote:
 == Quote from Justin Johansson (no spam.com)'s article
 Mentioned in the switch case statements thread, this probably should be
 a separate discussion thread.
 Is the comma operator "another piece of C cruft" that needs to be
 removed from D(2)?
 grauzone wrote:
  > Justin Johansson wrote:
  >> bearophile wrote:
  >>> What's bad about forcing people to write:
  >>> case A, B, C:
  >>>
  >>> Instead of:
  >>> case A:
  >>> case B:
  >>> case C:
  >>> ?
  >>>
  >>> Bye,
  >>> bearophile
  >>
  >> I don't know about "forcing people" to write such but perhaps it
  >> could be an "option for people" :-)
  >>
  >> Actually I quite like the brevity you propose but would it be a
  >> challenge for the comma operator?
  >>
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.

comma. The result is the value of the expression after the comma. int a = 1; int b = --a, ++a; assert(b == 1); assert(a == 1);

Axe. Looks like the only things it's good for are making code undreadable and abusing for loop syntax to... Make code unreadable. When the heck would this be significantly more readable, safer, or more concise than doing the equivalent without it? Also, from previous discussions I vaguely remember it's constraining other parts of the syntax.
Nov 16 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
dsimcha wrote:

 == Quote from Lutger (lutger.blijdestijn gmail.com)'s article

 int a = 1;
 int b = --a, ++a;
 assert(b == 1);
 assert(a == 1);

Axe. Looks like the only things it's good for are making code undreadable and abusing for loop syntax to... Make code unreadable. When the heck would this be significantly more readable, safer, or more concise than doing the equivalent without it? Also, from previous discussions I vaguely remember it's constraining other parts of the syntax.

Those discussions were about nice native tuple syntax. The only argument in favor of the comma operator I can remember is code-generation.
Nov 16 2009
parent testing - ignore this post <test test.com> writes:
Testing - ignore this post Leandro Lucarella Wrote:

 Lutger, el 16 de noviembre a las 23:27 me escribiste:
 dsimcha wrote:
 
 == Quote from Lutger (lutger.blijdestijn gmail.com)'s article

 int a = 1;
 int b = --a, ++a;
 assert(b == 1);
 assert(a == 1);

Axe. Looks like the only things it's good for are making code undreadable and abusing for loop syntax to... Make code unreadable. When the heck would this be significantly more readable, safer, or more concise than doing the equivalent without it? Also, from previous discussions I vaguely remember it's constraining other parts of the syntax.

Those discussions were about nice native tuple syntax. The only argument in favor of the comma operator I can remember is code-generation.

Which is a very dumb one. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Y cuando llegamos a nuestro hogar ella saca de su bolsillo derecho un casete de Ricardo Montaner y nos dice: "Ponelo! Ponelo!"; nos desilusionamos un poco, pero a esa altura... Todo da igual. -- Sidharta Kiwi

Nov 17 2009
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
dsimcha wrote:
<snip>
 Axe.  Looks like the only things it's good for are making code undreadable and
 abusing for loop syntax to...
 
 Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.
Nov 16 2009
next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Robert Jacques (sandford jhu.edu)'s article
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon <smjg_1998 yahoo.com>
 wrote:
 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

declarations/increments in a for loop.

But in D we have the scope statement that makes incrementing multiple variables trivial even in the presence of breaks and continues: for(size_t i = 0; i <= 10; i++) { scope(exit) otherVariable++; } It would be one thing if the comma operator were an innocent feature that wasn't hurting anything, but it uses up a very nice piece of syntax on something that usually serves to make code much less readable.
Nov 16 2009
prev sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon <smjg_1998 yahoo.com> 
 wrote:
 
 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code 
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.
Nov 16 2009
next sibling parent reply yigal chripun <yigal100 gmail.com> writes:
Robert Jacques Wrote:
 However, I imagine tuple(a++,b++) would have some overhead, which is  
 exactly what someone is trying to avoid by using custom for loops.
 
 Personally, I like using a..b => tuple(a,b), since it also solves the  
 multi-dimensional slicing and mixed indexing and slicing problems.

what overhead? It's all in your imagination :) a..b is confusing and bad UI. a..b means for humans the range of a till b and not the tuple of the two. if I see something like "hello"..42 I would assume the person who wrote this was high on something. multi dimentinal slicing should accept an integer range type and NOT a tuple.
Nov 16 2009
parent Yigal Chripun <yigal100 gmail.com> writes:
Robert Jacques wrote:
 On Tue, 17 Nov 2009 01:44:30 -0500, yigal chripun <yigal100 gmail.com> 
 wrote:
 
 Robert Jacques Wrote:
 However, I imagine tuple(a++,b++) would have some overhead, which is
 exactly what someone is trying to avoid by using custom for loops.

 Personally, I like using a..b => tuple(a,b), since it also solves the
 multi-dimensional slicing and mixed indexing and slicing problems.

what overhead? It's all in your imagination :) a..b is confusing and bad UI. a..b means for humans the range of a till b and not the tuple of the two. if I see something like "hello"..42 I would assume the person who wrote this was high on something. multi dimentinal slicing should accept an integer range type and NOT a tuple.

The unnecessary creation and setting of a tuple struct is by definition overhead. Also, containers will have non-integer slices, e.g. dictionary["hello".."world"], and strided ranges would even mix types: "hello"..42.."world". My point isn't that '..' was a better syntax than '(,)'. It's that '..' needs to change to something very much like a tuple and therefore could be used to kill two birds with one stone.

what tuple struct are you talking about? we are discussing real true tuples that are supported by the language type system (meaning at compile-time), not some library struct type. let me rephrase my sentence regarding slicing: struct R { int start, stride, end; } arrays should accept a list of the above R and a Dictionary should *not* implement slicing since that requires an order which dictionaries have no business to require. OrderedDictionary!(T) (if you really want such a beast) would accept: struct RR(T) { T start, end; int stride; } R and RR above are simplistic, real world impl. should make stride optional but the main point is that it is by no means a tuple. I see what you're saying about two birds with one stone but from my POV instead of replacing old cruft with a useful and friendly to use new feature you just added more cruft and hacks to poorly support said feature with unfriendly and confusing syntax.
Nov 17 2009
prev sibling next sibling parent reply downs <default_357-line yahoo.de> writes:
Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:
 
 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.
Nov 17 2009
parent Yigal Chripun <yigal100 gmail.com> writes:
Robert Jacques wrote:
 On Tue, 17 Nov 2009 11:38:19 -0500, Bill Baxter <wbaxter gmail.com> wrote:
 
 On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de> 
 wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

<snip> Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a form of compile-time tuples. This discussion seems to be about runtime tuples which currently don't have a nice syntax: you have to use tuple(a,b). And tuple(a,b) does have runtime overhead.

I think the point is that in something like this: auto foo = (a,b); foo.a += 2; foo.b += foo.a; // etc The tuple foo is allocated on the stack and the compiler knows where the a part and b part are, so the code generated should be absolutely no different from the code generated for: auto foo_a = a; auto foo_b = b; foo_a += 2; foo_b += foo_a; // etc So there doesn't need to be any "tuple overhead". --bb

But that isn't the expansion: for (int a = 0, b = 1; condition(); a++, b++) => int a = 0; int b = 0; while(condition) { auto temp = tuple(a++,b++); // creation of a struct on the stack } Now the optimizer might get rid of that temporary struct. Then again it might not (or its presence interferes with other optimizations). At the very least, some amount of code profiling or disassembly needs to be done.

why would it create a struct? it would probably do: int a = 0, b = 0; while (condition) { int temp_a = (a++); // temp_a == a + 1 int temp_b = (b++); } the above would most like be optimized by away. you can also take advantage of tuples with for loops, something like: for ( auto t = (0, 0); condition(); (t[1]++, t[2]++) ) {...} this is more flexible since you can't do with the current system: for (int a = 0, char b = 'a'; ; ) {...} because "int a = 0" is a declaration and not an expression. with tuples: for (auto t = (0, 'a'); ; ) {...}
Nov 17 2009
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Yigal Chripun wrote:
<snip>
 the only use case that will break is if the two increments are dependent 
 on the order (unless tuples are also evaluated from left to right):
 e.g.
 a + 5, b + a //

If you're overloading the + operator to have an externally visible side effect, you're probably obfuscating your code whether you use the comma operator or not. Moreover, how can you prove that nothing that uses the operator's return value can constitute a use case? Stewart.
Nov 18 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Stewart Gordon wrote:
 Yigal Chripun wrote:
 <snip>
 the only use case that will break is if the two increments are 
 dependent on the order (unless tuples are also evaluated from left to 
 right):
 e.g.
 a + 5, b + a //

If you're overloading the + operator to have an externally visible side effect, you're probably obfuscating your code whether you use the comma operator or not. Moreover, how can you prove that nothing that uses the operator's return value can constitute a use case? Stewart.

I don't follow you. What I said was that if you have the above in a for loop with a comma expression, you'd expect to *first* add 5 to a and *then* add the new a to b (comma operator defines left to right order of evaluation). tuples in general do not have to require a specific order since you keep all the results anyway, so the above could break. by defining tuples to be evaluated with the same order, the problem would be solved.
Nov 18 2009
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Yigal Chripun wrote:
 Stewart Gordon wrote:
 Yigal Chripun wrote:


 a + 5, b + a //



 I don't follow you. What I said was that if you have the above in a for 
 loop with a comma expression, you'd expect to *first* add 5 to a and 
 *then* add the new a to b (comma operator defines left to right order of 
 evaluation).

What "new a"? Normally, the expression "a + 5" doesn't alter the value of a at all. The only time it would is if a is of a programmer-defined type that has an opAdd function that does otherwise. Such semantics bending is bound to create more confusion than the comma operator.
 tuples in general do not have to require a specific order since you keep 
 all the results anyway, so the above could break. by defining tuples to 
 be evaluated with the same order, the problem would be solved.

Forcing an evaluation order on tuples would preclude common subexpression optimisation. Stewart.
Nov 19 2009
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Robert Jacques wrote:
<snip>
 However, I imagine tuple(a++,b++) would have some overhead, which is 
 exactly what someone is trying to avoid by using custom for loops.

Even if tuples do have an overhead, it would be a naive compiler that generates it in cases where nothing is done with it. Stewart.
Nov 18 2009
prev sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
dsimcha wrote:
 
 Axe.  Looks like the only things it's good for are making code undreadable and
 abusing for loop syntax to...
 
 Make code unreadable.
 
 When the heck would this be significantly more readable, safer, or more concise
 than doing the equivalent without it?  Also, from previous discussions I
vaguely
 remember it's constraining other parts of the syntax.

I've used them occasionally with regard to ref parameters Object foo(Object bar, ref bool flag); while( guard(bizz) && (fizz = foo(bizz,ok), ok)){} although I suppose it doesn't score so highly on the readable scale..
Nov 16 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
retard wrote:

 workplace. It might be valuable principle for your employer 

mah wut? :)
Nov 17 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Lutger Wrote:

 dsimcha wrote:
 
 == Quote from Justin Johansson (no spam.com)'s article
 Mentioned in the switch case statements thread, this probably should be
 a separate discussion thread.
 Is the comma operator "another piece of C cruft" that needs to be
 removed from D(2)?
 grauzone wrote:
  > Justin Johansson wrote:
  >> bearophile wrote:
  >>> What's bad about forcing people to write:
  >>> case A, B, C:
  >>>
  >>> Instead of:
  >>> case A:
  >>> case B:
  >>> case C:
  >>> ?
  >>>
  >>> Bye,
  >>> bearophile
  >>
  >> I don't know about "forcing people" to write such but perhaps it
  >> could be an "option for people" :-)
  >>
  >> Actually I quite like the brevity you propose but would it be a
  >> challenge for the comma operator?
  >>
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.

It is very simple, evaluates the expression before the comma and after the comma. The result is the value of the expression after the comma. int a = 1; int b = --a, ++a; assert(b == 1); assert(a == 1);

I'm no language lawyer, but I'm pretty sure that's not right. I don't think there's an order of evaluation rules. b could just as easilly end up with a value of 2.
Nov 16 2009
parent Lutger <lutger.blijdestijn gmail.com> writes:
Jason House wrote:

 Lutger Wrote:
 
 dsimcha wrote:
 
 == Quote from Justin Johansson (no spam.com)'s article
 Mentioned in the switch case statements thread, this probably should
 be a separate discussion thread.
 Is the comma operator "another piece of C cruft" that needs to be
 removed from D(2)?
 grauzone wrote:
  > Justin Johansson wrote:
  >> bearophile wrote:
  >>> What's bad about forcing people to write:
  >>> case A, B, C:
  >>>
  >>> Instead of:
  >>> case A:
  >>> case B:
  >>> case C:
  >>> ?
  >>>
  >>> Bye,
  >>> bearophile
  >>
  >> I don't know about "forcing people" to write such but perhaps it
  >> could be an "option for people" :-)
  >>
  >> Actually I quite like the brevity you propose but would it be a
  >> challenge for the comma operator?
  >>
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as
  >> int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.

It is very simple, evaluates the expression before the comma and after the comma. The result is the value of the expression after the comma. int a = 1; int b = --a, ++a; assert(b == 1); assert(a == 1);

I'm no language lawyer, but I'm pretty sure that's not right. I don't think there's an order of evaluation rules. b could just as easilly end up with a value of 2.

No I think it's right, also in C++: http://www.digitalmars.com/d/2.0/expression.html http://en.wikipedia.org/wiki/Sequence_point
Nov 16 2009
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Nov 16, 2009 at 10:12:57PM +0000, dsimcha wrote:
 Can someone please explain to me what the comma operator does? 

a = b, c; Is the same as: b; a = c; In the comma operation, the first thing is evaluate, and its result discarded. Then, the second thing (after the comma) is evaluated. The overall result of the comma operator is the result of the second statement. 1, 2 == 2 The usefulness is putting two statements together, where it only expects one, like inside the for loop, where the semicolon moves you on from the initialization to the condition. -- Adam D. Ruppe http://arsdnet.net
Nov 16 2009
next sibling parent Justin Johansson <no spam.com> writes:
Adam D. Ruppe wrote:
 On Mon, Nov 16, 2009 at 10:12:57PM +0000, dsimcha wrote:
 Can someone please explain to me what the comma operator does? 

a = b, c; Is the same as: b; a = c; In the comma operation, the first thing is evaluate, and its result discarded. Then, the second thing (after the comma) is evaluated. The overall result of the comma operator is the result of the second statement. 1, 2 == 2 The usefulness is putting two statements together, where it only expects one, like inside the for loop, where the semicolon moves you on from the initialization to the condition.

Speaking of for loops, it's not uncommon to use the comma operator in the 1st and 3rd expression places, e.g. (in C), something along the lines: void fun( char* start, int n) { int i; char* p; for ( i = 0, p = start; (i < n) && (*p != 0); ++i, ++p) { /* ... */ } }
Nov 16 2009
prev sibling next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Adam D. Ruppe wrote:
 On Mon, Nov 16, 2009 at 10:12:57PM +0000, dsimcha wrote:
 Can someone please explain to me what the comma operator does? 

a = b, c; Is the same as: b; a = c;

wrong. assignment has higher precedence than comma. change the first to a = (b, c); or the second to a = b; c;
Nov 16 2009
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Adam D. Ruppe wrote:
 On Mon, Nov 16, 2009 at 10:12:57PM +0000, dsimcha wrote:
 Can someone please explain to me what the comma operator does? 

a = b, c; Is the same as: b; a = c;

Wrong: Expression: AssignExpression AssignExpression , Expression So it's the same as a = b; c; Stewart.
Nov 16 2009
prev sibling next sibling parent Justin Johansson <no spam.com> writes:
dsimcha wrote:
  >> While ago, I got D multi-dimensional array syntax messed up and
  >> declared such an animal as
  >> int[3,4,5] which effectively ended up declaring the beast as int[5].
  >
  > The comma operator is another piece of C cruft that needs to go.
  >
  >> Cheers Justin

Can someone please explain to me what the comma operator does? I've seen this mentioned here before, but I really don't know. Then again, if the only people who use it are crufty old C language lawyers and people who have never programmed seriously in C before don't know about it, I guess that's an indicator that it's not worth much.

When (sub)expressions are separated with the comma operator, each (sub)expression is evaluated from left to right in turn (as if the individual (sub)expressions where separated by ; (semicolon) statement separator. The result returned by the overall expression is the result returned by the last (sub)expression (i.e., following the last comma). In the array example above, int[3,4,5], the dimension expression 3,4,5 evaluates 3 (a constant), then 4 (another constant), and then 5 (yet another constant) and returns 5, this being the last subexpression evaluated. This is why the array ended up being effectively a single dimension array of length 5. Justin
Nov 16 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Nov 16, 2009 at 05:00:56PM -0600, Ellery Newcomer wrote:
 wrong. assignment has higher precedence than comma.

Oh, duh. And I use that fact in for loops all the time too...
 change the first to
 
 	a = (b, c);

Right - this illustrates what I had in mind. -- Adam D. Ruppe http://arsdnet.net
Nov 16 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Nov 16, 2009 at 11:06:28PM +0000, Stewart Gordon wrote:
 Expression:
 	AssignExpression
 	AssignExpression , Expression
 
 So it's the same as
 
     a = b;
     c;

Right, moment of stupidity there for me. I should have put it in parenthesis.
 
 Stewart.

-- Adam D. Ruppe http://arsdnet.net
Nov 16 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code  
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.
Nov 16 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>  
wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon  
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code  
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.
Nov 16 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de>  
wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a form of compile-time tuples. This discussion seems to be about runtime tuples which currently don't have a nice syntax: you have to use tuple(a,b). And tuple(a,b) does have runtime overhead.
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de> wro=

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe. =A0Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
 =A0Make code unreadable.

<snip> Suppose you want the increment of a for loop to change two variables in parallel. =A0I don't call that making code unreadable. Stewart.

=A0Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a =3D 0, b =3D 1; condition(); a++, b++) {...} int a =3D 0, b =3D 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tup=




 the only use case that will break is if the two increments are
 dependent on the order (unless tuples are also evaluated from left to
 right):
 e.g.
 a + 5, b + a //

 I doubt it very much that anyone ever uses this, it's too unreadable
 to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b =3D> tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a form of compile-time tuples. This discussion seems to be about runtime tuples whi=

 currently don't have a nice syntax: you have to use tuple(a,b). And
 tuple(a,b) does have runtime overhead.

I think the point is that in something like this: auto foo =3D (a,b); foo.a +=3D 2; foo.b +=3D foo.a; // etc The tuple foo is allocated on the stack and the compiler knows where the a part and b part are, so the code generated should be absolutely no different from the code generated for: auto foo_a =3D a; auto foo_b =3D b; foo_a +=3D 2; foo_b +=3D foo_a; // etc So there doesn't need to be any "tuple overhead". --bb
Nov 17 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 11:38:19 -0500, Bill Baxter <wbaxter gmail.com> wrote:

 On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de>  
 wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

<snip> Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a form of compile-time tuples. This discussion seems to be about runtime tuples which currently don't have a nice syntax: you have to use tuple(a,b). And tuple(a,b) does have runtime overhead.

I think the point is that in something like this: auto foo = (a,b); foo.a += 2; foo.b += foo.a; // etc The tuple foo is allocated on the stack and the compiler knows where the a part and b part are, so the code generated should be absolutely no different from the code generated for: auto foo_a = a; auto foo_b = b; foo_a += 2; foo_b += foo_a; // etc So there doesn't need to be any "tuple overhead". --bb

But that isn't the expansion: for (int a = 0, b = 1; condition(); a++, b++) => int a = 0; int b = 0; while(condition) { auto temp = tuple(a++,b++); // creation of a struct on the stack } Now the optimizer might get rid of that temporary struct. Then again it might not (or its presence interferes with other optimizations). At the very least, some amount of code profiling or disassembly needs to be done.
Nov 17 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 01:44:30 -0500, yigal chripun <yigal100 gmail.com>  
wrote:

 Robert Jacques Wrote:
 However, I imagine tuple(a++,b++) would have some overhead, which is
 exactly what someone is trying to avoid by using custom for loops.

 Personally, I like using a..b => tuple(a,b), since it also solves the
 multi-dimensional slicing and mixed indexing and slicing problems.

what overhead? It's all in your imagination :) a..b is confusing and bad UI. a..b means for humans the range of a till b and not the tuple of the two. if I see something like "hello"..42 I would assume the person who wrote this was high on something. multi dimentinal slicing should accept an integer range type and NOT a tuple.

The unnecessary creation and setting of a tuple struct is by definition overhead. Also, containers will have non-integer slices, e.g. dictionary["hello".."world"], and strided ranges would even mix types: "hello"..42.."world". My point isn't that '..' was a better syntax than '(,)'. It's that '..' needs to change to something very much like a tuple and therefore could be used to kill two birds with one stone.
Nov 17 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 15:20:06 -0500, Yigal Chripun <yigal100 gmail.com>  
wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 11:38:19 -0500, Bill Baxter <wbaxter gmail.com>  
 wrote:

 On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford jhu.edu>  
 wrote:
 On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de>  
 wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun  
 <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe.  Looks like the only things it's good for are making code
 undreadable and
 abusing for loop syntax to...
  Make code unreadable.

<snip> Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple the only use case that will break is if the two increments are dependent on the order (unless tuples are also evaluated from left to right): e.g. a + 5, b + a // I doubt it very much that anyone ever uses this, it's too unreadable to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which is exactly what someone is trying to avoid by using custom for loops. Personally, I like using a..b => tuple(a,b), since it also solves the multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a form of compile-time tuples. This discussion seems to be about runtime tuples which currently don't have a nice syntax: you have to use tuple(a,b). And tuple(a,b) does have runtime overhead.

I think the point is that in something like this: auto foo = (a,b); foo.a += 2; foo.b += foo.a; // etc The tuple foo is allocated on the stack and the compiler knows where the a part and b part are, so the code generated should be absolutely no different from the code generated for: auto foo_a = a; auto foo_b = b; foo_a += 2; foo_b += foo_a; // etc So there doesn't need to be any "tuple overhead". --bb

for (int a = 0, b = 1; condition(); a++, b++) => int a = 0; int b = 0; while(condition) { auto temp = tuple(a++,b++); // creation of a struct on the stack } Now the optimizer might get rid of that temporary struct. Then again it might not (or its presence interferes with other optimizations). At the very least, some amount of code profiling or disassembly needs to be done.

why would it create a struct? it would probably do: int a = 0, b = 0; while (condition) { int temp_a = (a++); // temp_a == a + 1 int temp_b = (b++); } the above would most like be optimized by away. you can also take advantage of tuples with for loops, something like: for ( auto t = (0, 0); condition(); (t[1]++, t[2]++) ) {...} this is more flexible since you can't do with the current system: for (int a = 0, char b = 'a'; ; ) {...} because "int a = 0" is a declaration and not an expression. with tuples: for (auto t = (0, 'a'); ; ) {...}

*sigh* The reason the compiler would have to create a temporary struct, is because that's what a tuple is at runtime. Tuples need to be compact (like structs) so that they can be passed to functions, etc.
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Mon, 16 Nov 2009 17:08:58 -0600, Ellery Newcomer wrote:
 dsimcha wrote:
 
 Axe.  Looks like the only things it's good for are making code
 undreadable and abusing for loop syntax to...
 
 Make code unreadable.
 
 When the heck would this be significantly more readable, safer, or more
 concise than doing the equivalent without it?  Also, from previous
 discussions I vaguely remember it's constraining other parts of the
 syntax.

I've used them occasionally with regard to ref parameters Object foo(Object bar, ref bool flag); while( guard(bizz) && (fizz = foo(bizz,ok), ok)){} although I suppose it doesn't score so highly on the readable scale..

This kind of code wouldn't go pass the code review process at my workplace. It might be valuable principle for your employer if you're paid by the line, though..
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Mon, 16 Nov 2009 18:22:24 -0500, Adam D. Ruppe wrote:

 On Mon, Nov 16, 2009 at 05:00:56PM -0600, Ellery Newcomer wrote:
 wrong. assignment has higher precedence than comma.

Oh, duh. And I use that fact in for loops all the time too...
 change the first to
 
 	a = (b, c);

Right - this illustrates what I had in mind.

I think this pretty much sums up how error prone the feature can be even in the hands of an experienced programmer..
Nov 17 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 18 Nov 2009 15:01:10 -0500, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 Robert Jacques wrote:
 <snip>
 However, I imagine tuple(a++,b++) would have some overhead, which is  
 exactly what someone is trying to avoid by using custom for loops.

Even if tuples do have an overhead, it would be a naive compiler that generates it in cases where nothing is done with it. Stewart.

Actually, as the current compiler knows nothing about tuples, I'd have to call it very naive with respect to tuple optimization. :)
Nov 18 2009
prev sibling parent retard <re tard.com.invalid> writes:
Wed, 18 Nov 2009 18:38:25 -0500, Robert Jacques wrote:

 On Wed, 18 Nov 2009 15:01:10 -0500, Stewart Gordon <smjg_1998 yahoo.com>
 wrote:
 
 Robert Jacques wrote:
 <snip>
 However, I imagine tuple(a++,b++) would have some overhead, which is
 exactly what someone is trying to avoid by using custom for loops.

Even if tuples do have an overhead, it would be a naive compiler that generates it in cases where nothing is done with it. Stewart.

Actually, as the current compiler knows nothing about tuples, I'd have to call it very naive with respect to tuple optimization. :)

It does. Try $ strings dmd on *nix or compiling the following code: template Tuple(T...) { alias T Tuple; } int a, b; Tuple!(a, b) = Tuple!(1,2);
Nov 19 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Justin Johansson" <no spam.com> wrote in message 
news:hdsi9d$ufg$1 digitalmars.com...
 Mentioned in the switch case statements thread, this probably should be a 
 separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be removed 
 from D(2)?

Aside from the for loop (which could be special cased or just simply rewritten), I've never used, or had reason to use, the comma operator in all the programming I've ever done in D, C/C++ (which I used to use all the time), or any other language. I strongly vote "ditch it". There are far better potential uses for a comma anyway. Speaking of C cruft, why the hell do we still have C's god-awful octal syntax? Everyone but Walter's complained about it. And I don't want to hear "to help port C code", because the whole reason I got started on D in the first place was to get away from idiotic C designs. Besides, it's not like "0([0-9]+)" is hard to grep for.
Nov 16 2009
parent reply Justin Johansson <no spam.com> writes:
Nick Sabalausky wrote:
 "Justin Johansson" <no spam.com> wrote in message 
 news:hdsi9d$ufg$1 digitalmars.com...
 Mentioned in the switch case statements thread, this probably should be a 
 separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be removed 
 from D(2)?

Aside from the for loop (which could be special cased or just simply rewritten), I've never used, or had reason to use, the comma operator in all the programming I've ever done in D, C/C++ (which I used to use all the time), or any other language. I strongly vote "ditch it". There are far better potential uses for a comma anyway. Speaking of C cruft, why the hell do we still have C's god-awful octal syntax? Everyone but Walter's complained about it. And I don't want to hear "to help port C code", because the whole reason I got started on D in the first place was to get away from idiotic C designs. Besides, it's not like "0([0-9]+)" is hard to grep for.

Hey, Nick. Don't try and hijack *my* thread; go get your own <expletives deleted> thread. Ha. :-)
Nov 16 2009
parent "Nick Sabalausky" <a a.a> writes:
"Justin Johansson" <no spam.com> wrote in message 
news:hdskj6$12b1$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Justin Johansson" <no spam.com> wrote in message 
 news:hdsi9d$ufg$1 digitalmars.com...
 Mentioned in the switch case statements thread, this probably should be 
 a separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be 
 removed from D(2)?

Aside from the for loop (which could be special cased or just simply rewritten), I've never used, or had reason to use, the comma operator in all the programming I've ever done in D, C/C++ (which I used to use all the time), or any other language. I strongly vote "ditch it". There are far better potential uses for a comma anyway. Speaking of C cruft, why the hell do we still have C's god-awful octal syntax? Everyone but Walter's complained about it. And I don't want to hear "to help port C code", because the whole reason I got started on D in the first place was to get away from idiotic C designs. Besides, it's not like "0([0-9]+)" is hard to grep for.

Hey, Nick. Don't try and hijack *my* thread; go get your own <expletives deleted> thread. Ha. :-)

Heh, that is actually a good point. My apologies. :)
Nov 16 2009
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Mon, Nov 16, 2009 at 2:04 PM, Justin Johansson <no spam.com> wrote:
 Mentioned in the switch case statements thread, this probably should be a
 separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be removed
 from D(2)?


 grauzone wrote:
 Justin Johansson wrote:
 bearophile wrote:
 What's bad about forcing people to write:
 case A, B, C:

 Instead of:
 case A:
 case B:
 case C:
 ?

 Bye,
 bearophile

I don't know about "forcing people" to write such but perhaps it could be an "option for people" :-) Actually I quite like the brevity you propose but would it be a challenge for the comma operator? While ago, I got D multi-dimensional array syntax messed up and declared such an animal as int[3,4,5] which effectively ended up declaring the beast as int[5].

The comma operator is another piece of C cruft that needs to go.


Note that if comma-as-sequencer was removed, and repurposed as a tuple literal (with "a,b" making a tuple), and if we specify that tuple elements are evaluated in order, then I think this would work as a replacement for the current comma operator: (expr1,expr2,expr3)[$-1] But the nice thing is you can get the effect of a comma operator that evaluates to the value of any expression in the sequence, just using different indices. Not sure how odious people would find forcing an order of eval on tuples, though. In the context of a for-loop, you don't care what the value is, so it would work as a tuple as-is. The tuple itself would be the value: for(; i<10; ++i,++j) // just works Though, probably this case needs some special treatment to continue working: int i=0,j=0 --bb
Nov 16 2009
next sibling parent Justin Johansson <no spam.com> writes:
Bill Baxter wrote:
 On Mon, Nov 16, 2009 at 2:04 PM, Justin Johansson <no spam.com> wrote:
 Mentioned in the switch case statements thread, this probably should be a
 separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be removed
 from D(2)?


 grauzone wrote:
 Justin Johansson wrote:
 bearophile wrote:
 What's bad about forcing people to write:
 case A, B, C:

 Instead of:
 case A:
 case B:
 case C:
 ?

 Bye,
 bearophile

be an "option for people" :-) Actually I quite like the brevity you propose but would it be a challenge for the comma operator? While ago, I got D multi-dimensional array syntax messed up and declared such an animal as int[3,4,5] which effectively ended up declaring the beast as int[5].



Note that if comma-as-sequencer was removed, and repurposed as a tuple literal (with "a,b" making a tuple), and if we specify that tuple elements are evaluated in order, then I think this would work as a replacement for the current comma operator: (expr1,expr2,expr3)[$-1] But the nice thing is you can get the effect of a comma operator that evaluates to the value of any expression in the sequence, just using different indices. Not sure how odious people would find forcing an order of eval on tuples, though. In the context of a for-loop, you don't care what the value is, so it would work as a tuple as-is. The tuple itself would be the value: for(; i<10; ++i,++j) // just works Though, probably this case needs some special treatment to continue working: int i=0,j=0 --bb

Whilst I still have some affection for the C-style comma operator (particularly wrt for loop construct), but since the Waterfront Real Estate of operators is extremely limited (borrowing a phrase from Walter), I think this is an excellent suggestion to re-purpose the comma operator for higher-value utilization by tuples. Would the "special treatments" be not too difficult to resolve? beers, Justin
Nov 16 2009
prev sibling next sibling parent reply grauzone <none example.net> writes:
Bill Baxter wrote:
 On Mon, Nov 16, 2009 at 2:04 PM, Justin Johansson <no spam.com> wrote:
 Mentioned in the switch case statements thread, this probably should be a
 separate discussion thread.

 Is the comma operator "another piece of C cruft" that needs to be removed
 from D(2)?


 grauzone wrote:
 Justin Johansson wrote:
 bearophile wrote:
 What's bad about forcing people to write:
 case A, B, C:

 Instead of:
 case A:
 case B:
 case C:
 ?

 Bye,
 bearophile

be an "option for people" :-) Actually I quite like the brevity you propose but would it be a challenge for the comma operator? While ago, I got D multi-dimensional array syntax messed up and declared such an animal as int[3,4,5] which effectively ended up declaring the beast as int[5].



Note that if comma-as-sequencer was removed, and repurposed as a tuple literal (with "a,b" making a tuple), and if we specify that tuple elements are evaluated in order, then I think this would work as a replacement for the current comma operator: (expr1,expr2,expr3)[$-1] But the nice thing is you can get the effect of a comma operator that evaluates to the value of any expression in the sequence, just using different indices. Not sure how odious people would find forcing an order of eval on tuples, though. In the context of a for-loop, you don't care what the value is, so it would work as a tuple as-is. The tuple itself would be the value: for(; i<10; ++i,++j) // just works

That's nice.
 Though, probably this case needs some special treatment to continue working:
 
   int i=0,j=0

Does it need to be a special case? "int i=0,j=0" is one declaration (with variables separated by a comma), not something glued together with the comma operator. Of course normal declarations like "int i, j;" also would continue to work. Not all commas are part of a comma expression.
 --bb

Nov 16 2009
next sibling parent reply Justin Johansson <no spam.com> writes:
grauzone wrote:
 Note that if comma-as-sequencer was removed, and repurposed as a tuple
 literal  (with "a,b"  making a tuple), and if we specify that tuple
 elements are evaluated in order, then I think this would work as a
 replacement for the current comma operator:

   (expr1,expr2,expr3)[$-1]

 But the nice thing is you can get the effect of a comma operator that
 evaluates to the value of any expression in the sequence, just using
 different indices.
 Not sure how odious people would find forcing an order of eval on
 tuples, though.

 In the context of a for-loop, you don't care what the value is, so it
 would work as a tuple as-is.  The tuple itself would be the value:

   for(; i<10; ++i,++j)  // just works

That's nice.
 Though, probably this case needs some special treatment to continue 
 working:

   int i=0,j=0

Does it need to be a special case? "int i=0,j=0" is one declaration (with variables separated by a comma), not something glued together with the comma operator. Of course normal declarations like "int i, j;" also would continue to work. Not all commas are part of a comma expression.

Great. Sounds like problem solved in that there is no problem. So how do people feel about bill's suggestion to progress the issue further? Be good to get some comments from higher-up (Walter, Andrei)? Predict bearophile will chime in on this one too?
Nov 16 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.
 
 So how do people feel about bill's suggestion to progress the issue
 further?
 
 Be good to get some comments from higher-up (Walter, Andrei)?
 
 Predict bearophile will chime in on this one too?

The real problem is you'd end up with a tuple syntax identical to a valid c syntax. If D silently accepts it, but does something different, it's a no go.
Nov 16 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Leandro Lucarella wrote:
 Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.

 So how do people feel about bill's suggestion to progress the issue
 further?

 Be good to get some comments from higher-up (Walter, Andrei)?

 Predict bearophile will chime in on this one too?

valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );
Nov 17 2009
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Nov 17, 09 23:44, Ellery Newcomer wrote:
 Leandro Lucarella wrote:
 Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.

 So how do people feel about bill's suggestion to progress the issue
 further?

 Be good to get some comments from higher-up (Walter, Andrei)?

 Predict bearophile will chime in on this one too?

valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );

These are not code ported from *C*.
Nov 17 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
KennyTM~ wrote:
 On Nov 17, 09 23:44, Ellery Newcomer wrote:
 Leandro Lucarella wrote:
 Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.

 So how do people feel about bill's suggestion to progress the issue
 further?

 Be good to get some comments from higher-up (Walter, Andrei)?

 Predict bearophile will chime in on this one too?

valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );

These are not code ported from *C*.

all but the second fun1 are, and it could easily exist in D
Nov 17 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Leandro Lucarella wrote:
 Ellery Newcomer, el 17 de noviembre a las 12:58 me escribiste:
 void fun1(int a);
 void fun1(Tuple!(int,int) a);

 fun1( (a=fizbang(), a+b) );



We agree except for the *easily*. On the contrary, I think it would be extremely rare.

I think by 'easily', I didn't exactly mean 'likely'. Sure it would be rare. Use of comma operator is pretty uncommon itself, from what I've seen (which doesn't include a lot of C code, however). I'm just saying this is one instance where it would cause problems. want another? how about this? int fizzbizz; int* bar; int i = (fizzbizz, bar)[0];
Nov 17 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

int[] i; auto a = (i)[0]; what does this do?
Nov 17 2009
parent reply KennyTM~ <kennytm gmail.com> writes:
On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

int[] i; auto a = (i)[0]; what does this do?

(i) should not construct a tuple. Probably (i,).
Nov 17 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Bill Baxter:
 (i) should not construct a tuple. Probably (i,).

That's Python's solution and it seems to work out ok.

Tuple syntax for 0, 1, n items is one of the few things that I don't like of Python :-) In Python this is an empty tuple: () Or: tuple() This is a tuple with 1 item: x, This is a tuple with 3 items x,y,z Parentheses are not necessary unless you want an empty tuple. Bye, bearophile
Nov 17 2009
prev sibling next sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
KennyTM~ wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

int[] i; auto a = (i)[0]; what does this do?

(i) should not construct a tuple. Probably (i,).

I agree, a tuple of one element (doesn't matter what type, array in this case) should be semantically identical to that single element. proper semantics for language supported tuples should IMO include: 1) syntax to explicitly [de]construct tuples and no auto-flattening 2) a tuple of one element is identical to a scalar: int a = 5; // scalar integer auto b = (5); // tuple of one integer a == b // is true 3) function's argument list is a tuple like in ML: void foo(int a, char b); int a = 5; char b ='a'; auto tup = (5, 'a'); foo(a, b) is identical to foo(t); 4) unit type defined by the empty tuple instead of c-like void
Nov 17 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Yigal Chripun wrote:
 KennyTM~ wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

int[] i; auto a = (i)[0]; what does this do?

(i) should not construct a tuple. Probably (i,).

I agree, a tuple of one element (doesn't matter what type, array in this case) should be semantically identical to that single element. proper semantics for language supported tuples should IMO include: 1) syntax to explicitly [de]construct tuples and no auto-flattening 2) a tuple of one element is identical to a scalar: int a = 5; // scalar integer auto b = (5); // tuple of one integer a == b // is true 3) function's argument list is a tuple like in ML: void foo(int a, char b); int a = 5; char b ='a'; auto tup = (5, 'a'); foo(a, b) is identical to foo(t);

does ML have any equivalent of template parameters? eg foo!(1,int);
 4) unit type defined by the empty tuple instead of c-like void

Nov 17 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Ellery Newcomer wrote:
  foo(a, b) is identical to foo(t);
 
 does ML have any equivalent of template parameters? eg
 
 foo!(1,int);
 

I'd suggest reading the wikipedia page about ML. in short, ML is a strongly, statically typed language much like D, but doesn't require type annotations. it uses the Hindley-Milner type inference algorithm (named after its creators) which infers the types at compile-time. here's a naive factorial implementation in ML: fun f (0 : int) : int = 1 | f (n : int) : int = n * f (n-1) you can provide type annotations as above if you want to specify explicit types. here's another function: fun foo (n) = n + n if you use foo(3.5) the compiler would use a version of foo with signature: real -> real but if you use foo(4) the compiler will use a version of foo with signature int -> int note that I didn't need to specify the type as parameter. foo's signature is actually: `a -> `a which is like doing in D: T foo(T) (T n) { return n + n; } but unlike ML, in D/C++ you need to provide the type parameter yourself. does that answer your question?
Nov 18 2009
parent yigal chripun <yigal100 gmail.com> writes:
retard Wrote:

 Thu, 19 Nov 2009 00:00:00 +0200, Yigal Chripun wrote:
 
 Ellery Newcomer wrote:
   foo(a, b) is identical to foo(t);
 
 does ML have any equivalent of template parameters? eg
 
 foo!(1,int);


 foo's signature is actually: `a -> `a which is like doing in D: T foo(T)
 (T n) { return n + n; } but unlike ML, in D/C++ you need to provide the
 type parameter yourself.
 
 does that answer your question?

A bit more precise answer would be 'no'. ML does not support programming with types directly. There is no way to pass stuff from value world to type world and vice versa like in D.

I wouldn't say it's a decisive No. there are several extensions to ML like MetaML and MacroML that do have such capabilities. There are also ML inspired languages like Nemerle which provide very powerful AST macro systems.
Nov 19 2009
prev sibling next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 Yes, Yigal said basically that.  The question I have is what practical
 difference does that make to the language?
 Seems no different from defining the empty tuple to be void, then
 renaming void to unit.
 
 
 --bb

If you have unit distinct from void, you could use it for what Andrei mentioned a while back. Something to do with determining a function will never return because it always throws, etc.
Nov 17 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Ellery Newcomer wrote:
 Bill Baxter wrote:
 Yes, Yigal said basically that.  The question I have is what practical
 difference does that make to the language?
 Seems no different from defining the empty tuple to be void, then
 renaming void to unit.


 --bb

If you have unit distinct from void, you could use it for what Andrei mentioned a while back. Something to do with determining a function will never return because it always throws, etc.

then again, maybe not.
Nov 17 2009
parent reply Justin Johansson <no spam.com> writes:
Ellery Newcomer wrote:
 Ellery Newcomer wrote:
 Bill Baxter wrote:
 Yes, Yigal said basically that.  The question I have is what practical
 difference does that make to the language?
 Seems no different from defining the empty tuple to be void, then
 renaming void to unit.


 --bb

mentioned a while back. Something to do with determining a function will never return because it always throws, etc.

then again, maybe not.

From my memory of Scala, the top and bottom types are called Unit and Nothing respectively. Unit is analogous to C,C++,D,Java void and Nothing is the type of that returned by a function that never returns (in other words nothing). I think the latter (the Nothing type) is what Andrei was talking about before. FYI, a lot of articles about types systems are rather arduous to read but I found this one written in more lay-speak by James Iry who is a Scala advocate. Getting to the Bottom of Nothing At All. http://james-iry.blogspot.com/2009/08/getting-to-bottom-of-nothing-at-all.html Enjoy the read; all about nothing, bits about tuples. No warranty for academic accuracy though. -- Justin Johansson
Nov 17 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Justin Johansson wrote:
 Ellery Newcomer wrote:
 Ellery Newcomer wrote:
 Bill Baxter wrote:
 Yes, Yigal said basically that.  The question I have is what practical
 difference does that make to the language?
 Seems no different from defining the empty tuple to be void, then
 renaming void to unit.


 --bb

mentioned a while back. Something to do with determining a function will never return because it always throws, etc.

then again, maybe not.

From my memory of Scala, the top and bottom types are called Unit and Nothing respectively. Unit is analogous to C,C++,D,Java void and Nothing is the type of that returned by a function that never returns (in other words nothing). I think the latter (the Nothing type) is what Andrei was talking about before. FYI, a lot of articles about types systems are rather arduous to read but I found this one written in more lay-speak by James Iry who is a Scala advocate. Getting to the Bottom of Nothing At All. http://james-iry.blogspot.com/2009/08/getting-to-bottom-of-nothing-at-all.html Enjoy the read; all about nothing, bits about tuples. No warranty for academic accuracy though. -- Justin Johansson

nice link
Nov 17 2009
prev sibling parent Yigal Chripun <yigal100 gmail.com> writes:
Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 3:57 PM, retard <re tard.com.invalid> wrote:
 Tue, 17 Nov 2009 14:38:57 -0800, Bill Baxter wrote:

 I agree, a tuple of one element (doesn't matter what type, array in
 this case) should be semantically identical to that single element.

 proper semantics for language supported tuples should IMO include: 1)
 syntax to explicitly [de]construct tuples and no auto-flattening 2) a
 tuple of one element is identical to a scalar:
   int a = 5; // scalar integer
   auto b = (5); // tuple of one integer a == b // is true

And properties? 5[0] == 5? 5.length == 1? If not that could be painful for functions that process generic N-tuples. If so then what does that do if the "scalar" type happens to be float*?

recursively from the Pair type, e.g. Pair[int,int], Pair[int, Pair [int,int]] === (int,int,int). And have a special indexing syntax with 1- based indexing.

That wasn't really the question. It was what should 5[0] do in D, if scalars are considered to be 1-tuples? I think that's a killer for 1-tuple / scalar equivalence in D. Neither behavior is acceptable in my opinion. So it seems you can't have 1-tuple/scalar equivalence unless you have a distinct tuple-indexing syntax. Right now std.typecons.tuple uses x.at!(0) because you can't have a x[i] return different types, but the built-in "A..." template tuples do it. So that's something that needs to be fixed anyway, because "good for me but not for thee" is lame. (Took that phrase from a review of Go...) I think probably D should allow a templated opIndex!(int) so that user types can implement tuple-like indexing where each index could be a different type. Or we should try to come up with another syntax for indexing tuples.
 3) function's argument list is a tuple like in ML:
   void foo(int a, char b);
   int a = 5; char b ='a';
   auto tup = (5, 'a');
   foo(a, b) is identical to foo(t);



That does seem to kill that idea.
 That seems like a kind of auto-flattening.  Shouldn't (t) be a tuple of
 a tuple?
 What if you have an actual tuple in the signature, like void foo((int
 a,char b))?
 Or you have both overloads -- foo(int,char) and foo((int,char)) I think
 I like Python's explicit "explode tuple" syntax better.
    foo(*t)
 Probably that syntax won't work for D, but I'd prefer explicit
 flattening over implicit.

 4) unit type defined by the empty tuple instead of c-like void

give an aesthetically pleasing meaning to void/unit?


Yes, Yigal said basically that. The question I have is what practical difference does that make to the language? Seems no different from defining the empty tuple to be void, then renaming void to unit. --bb

to clarify what I meant regarding function args list lets look at a few ML examples: fun f1() = () f1 is unit -> unit fun f2 (a) = a f2 `a -> `a fun f3 (a, b, (c, d)) = a + b + c + d f3 is (`a, `a, (`a, `a)) -> `a it doesn't auto flatten the tuples but the list of parameters is equivalent to a tuple. regarding unit type, it has by definition exactly one value, so a function that is defined now in D to return "void" would return that value and than it's perfectly legal to have foo(bar()) when bar returns a unit type.
Nov 17 2009
prev sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


That's Python's solution and it seems to work out ok. --bb

How do we express tuple types? Since we have tuple expression syntactic support, we should have tuple type syntactic support. Cuz I'm going to want stuff like Tuple!(int,int) [] lst; These won't work: [int,int] [] lst; (int,int) [] lst; //want {int,int} [] lst; these might: (int,int) [] lst; //bleach, regardless of what symbol ' ' is (,int,int) [] lst; //bleach alias (int,int) T; T [] lst; //bleach bleach bleach int,int [] lst; //requires tuple expressions be enclosed in () hmmmm... actually, types vs expressions are already syntactically ambiguous, so (int,int) [] lst; doesn't lose much. It's not the kind of thing we should be encouraging, though.
Nov 17 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Ellery Newcomer wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


--bb

How do we express tuple types? Since we have tuple expression syntactic support, we should have tuple type syntactic support. Cuz I'm going to want stuff like Tuple!(int,int) [] lst; These won't work: [int,int] [] lst; (int,int) [] lst; //want {int,int} [] lst; these might: (int,int) [] lst; //bleach, regardless of what symbol ' ' is (,int,int) [] lst; //bleach alias (int,int) T; T [] lst; //bleach bleach bleach int,int [] lst; //requires tuple expressions be enclosed in () hmmmm...

and you'd have to enclose the types in () in nonstatement locations
 
 
 actually, types vs expressions are already syntactically ambiguous, so
 (int,int) [] lst; doesn't lose much. It's not the kind of thing we
 should be encouraging, though.

Nov 17 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Ellery Newcomer wrote:
 Ellery Newcomer wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


--bb

support, we should have tuple type syntactic support. Cuz I'm going to want stuff like Tuple!(int,int) [] lst; These won't work: [int,int] [] lst; (int,int) [] lst; //want {int,int} [] lst; these might: (int,int) [] lst; //bleach, regardless of what symbol ' ' is (,int,int) [] lst; //bleach alias (int,int) T; T [] lst; //bleach bleach bleach int,int [] lst; //requires tuple expressions be enclosed in () hmmmm...

and you'd have to enclose the types in () in nonstatement locations

which is a big bleach
 actually, types vs expressions are already syntactically ambiguous, so
 (int,int) [] lst; doesn't lose much. It's not the kind of thing we
 should be encouraging, though.


Nov 17 2009
prev sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 3:01 PM, Ellery Newcomer
 <ellery-newcomer utulsa.edu> wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


--bb

These won't work: ... (int,int) [] lst; //want

Why won't that work? You may be right, but that particular declaration doesn't seem ambiguous to me. --bb

foo!( (i,i) ) (); compiler doesn't know if 'i' is a type or a variable. Like I said, the problem already exists for eg foo!( i ) (); and isn't semantically ambiguous (as far as I know..), so it is doable. at statement level, it would require a lot of lookahead to distinguish eg (i,i)[0] = blah; (i,i)[0] blah; Not my idea of good language design (one character deep in the production - can you say fortran :) actually fortran is worse, it discards whitespace as token separators)
Nov 17 2009
next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Ellery Newcomer wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 3:01 PM, Ellery Newcomer
 <ellery-newcomer utulsa.edu> wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


--bb

These won't work: ... (int,int) [] lst; //want

declaration doesn't seem ambiguous to me. --bb

foo!( (i,i) ) (); compiler doesn't know if 'i' is a type or a variable.

by compiler I mean parser. compiler eventually will figure it out.
 Like I said, the problem already exists for eg
 
 foo!( i ) ();
 
 and isn't semantically ambiguous (as far as I know..), so it is doable.
 
 at statement level, it would require a lot of lookahead to distinguish eg
 
 (i,i)[0] = blah;
 (i,i)[0] blah;
 
 Not my idea of good language design (one character deep in the
 production - can you say fortran :) actually fortran is worse, it
 discards whitespace as token separators)

Nov 17 2009
prev sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Nov 18, 09 07:25, Ellery Newcomer wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 3:01 PM, Ellery Newcomer
 <ellery-newcomer utulsa.edu>  wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~<kennytm gmail.com>  wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


--bb

These won't work: ... (int,int) [] lst; //want

Why won't that work? You may be right, but that particular declaration doesn't seem ambiguous to me. --bb

foo!( (i,i) ) (); compiler doesn't know if 'i' is a type or a variable. Like I said, the problem already exists for eg foo!( i ) (); and isn't semantically ambiguous (as far as I know..), so it is doable. at statement level, it would require a lot of lookahead to distinguish eg (i,i)[0] = blah; (i,i)[0] blah; Not my idea of good language design (one character deep in the production - can you say fortran :) actually fortran is worse, it discards whitespace as token separators)

int[2][2][2][2][2][2][2][2][2][2] a; alias int b; a[1][1][1][1][1][1][1][1][1][1] = c; b[1][1][1][1][1][1][1][1][1][1] d; still a lot of look ahead :p
Nov 17 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
KennyTM~ wrote:
 On Nov 18, 09 07:25, Ellery Newcomer wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 3:01 PM, Ellery Newcomer
 <ellery-newcomer utulsa.edu>  wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~<kennytm gmail.com>  wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same
 thing in
 D.

auto a = (i)[0]; what does this do?


--bb

These won't work: ... (int,int) [] lst; //want

Why won't that work? You may be right, but that particular declaration doesn't seem ambiguous to me. --bb

foo!( (i,i) ) (); compiler doesn't know if 'i' is a type or a variable. Like I said, the problem already exists for eg foo!( i ) (); and isn't semantically ambiguous (as far as I know..), so it is doable. at statement level, it would require a lot of lookahead to distinguish eg (i,i)[0] = blah; (i,i)[0] blah; Not my idea of good language design (one character deep in the production - can you say fortran :) actually fortran is worse, it discards whitespace as token separators)

int[2][2][2][2][2][2][2][2][2][2] a; alias int b; a[1][1][1][1][1][1][1][1][1][1] = c; b[1][1][1][1][1][1][1][1][1][1] d; still a lot of look ahead :p

Indeed. The original syntax I used Tuple!(int,int) [] lst; has the same problem.
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 4:58 PM, Ellery Newcomer
<ellery-newcomer utulsa.edu> wrote:
 Bill Baxter wrote:
 Yes, Yigal said basically that. =A0The question I have is what practical
 difference does that make to the language?
 Seems no different from defining the empty tuple to be void, then
 renaming void to unit.


 --bb

If you have unit distinct from void, you could use it for what Andrei mentioned a while back. Something to do with determining a function will never return because it always throws, etc.

Hmm, well Yigal specifically said "instead of C-like void". Not "in addition to". --bb
Nov 17 2009
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 9:05 PM, Yigal Chripun <yigal100 gmail.com> wrote:
 to clarify what I meant regarding function args list lets look at a few ML
 examples:


 fun f1() = ()
 f1 is unit -> unit

 fun f2 (a) = a
 f2 `a -> `a

 fun f3 (a, b, (c, d)) = a + b + c + d
 f3 is (`a, `a, (`a, `a)) -> `a

 it doesn't auto flatten the tuples but the list of parameters is equivalent
 to a tuple.

Ok, but I think retard is right that tuple==parameter list equivalence is going to be hard to make happen in a language like D, since D has all these storage classes for parameters.
 regarding unit type, it has by definition exactly one value, so a function
 that is defined now in D to return "void" would return that value and than
 it's perfectly legal to have foo(bar()) when bar returns a unit type.

I see. That might come in handy sometimes. Thanks for explaining. But it seems like something we could make happen regardless of tuples. In C/C++ you can declare foo as void foo(void); It makes sense that a function returning void should be allowed to chain with a function taking void. --bb
Nov 18 2009
parent reply yigal chripun <yigal100 gmail.com> writes:
You're remark of function chaining reminded me of a nice feture that a few OOP
languages provide:

// pseudo syntax
auto obj = new Object();
obj foo() ; bar() ; goo() 

foo, bar and goo above are three mesages (methods) that are sent to the same
object. i.e. it's the same as doing:
obj.foo();
obj.bar();
obj.goo();

this means the functions can return void instead of returning this like you'd
do in C++/D. I think it provides a cleaner conceptual separation between
multiple messages sent to one object and real chaining when foo returns obj2
which then receives message bar and so on.
Nov 18 2009
next sibling parent Justin Johansson <no spam.com> writes:
yigal chripun wrote:
 You're remark of function chaining reminded me of a nice feture that a few OOP
languages provide:
 
 // pseudo syntax
 auto obj = new Object();
 obj foo() ; bar() ; goo() 
 
 foo, bar and goo above are three mesages (methods) that are sent to the same
object. i.e. it's the same as doing:
 obj.foo();
 obj.bar();
 obj.goo();
 
 this means the functions can return void instead of returning this like you'd
do in C++/D. I think it provides a cleaner conceptual separation between
multiple messages sent to one object and real chaining when foo returns obj2
which then receives message bar and so on.

This has to be flame-bait for sure! :-)
Nov 18 2009
prev sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
yigal chripun wrote:
 You're remark of function chaining reminded me of a nice feture that a few OOP
languages provide:
 
 // pseudo syntax
 auto obj = new Object();
 obj foo() ; bar() ; goo() 
 
 foo, bar and goo above are three mesages (methods) that are sent to the same
object. i.e. it's the same as doing:
 obj.foo();
 obj.bar();
 obj.goo();
 
 this means the functions can return void instead of returning this like you'd
do in C++/D. I think it provides a cleaner conceptual separation between
multiple messages sent to one object and real chaining when foo returns obj2
which then receives message bar and so on.

with (auto obj = new Object) { foo; bar; goo; } Behold. ;)
Nov 18 2009
prev sibling parent retard <re tard.com.invalid> writes:
Wed, 18 Nov 2009 02:36:35 -0800, Bill Baxter wrote:

 On Tue, Nov 17, 2009 at 9:05 PM, Yigal Chripun <yigal100 gmail.com>
 regarding unit type, it has by definition exactly one value, so a
 function that is defined now in D to return "void" would return that
 value and than it's perfectly legal to have foo(bar()) when bar returns
 a unit type.

I see. That might come in handy sometimes. Thanks for explaining. But it seems like something we could make happen regardless of tuples. In C/C++ you can declare foo as void foo(void); It makes sense that a function returning void should be allowed to chain with a function taking void.

Aye. It doesn't really matter what you call it. Another difference are the implicit type conversions. The () value cannot be coerced to some other type without leaking immensive amounts of blood and sweat.
Nov 18 2009
prev sibling next sibling parent KennyTM~ <kennytm gmail.com> writes:
On Nov 18, 09 02:58, Ellery Newcomer wrote:
 KennyTM~ wrote:
 On Nov 17, 09 23:44, Ellery Newcomer wrote:
 Leandro Lucarella wrote:
 Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.

 So how do people feel about bill's suggestion to progress the issue
 further?

 Be good to get some comments from higher-up (Walter, Andrei)?

 Predict bearophile will chime in on this one too?

valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );

These are not code ported from *C*.

all but the second fun1 are, and it could easily exist in D

The only guarantee I knew is code valid in C either gives the same result in C, or fails to compile. Removing the 2nd fun1 which is invalid in C anyway, having a tuple syntax, fun1 simply fails to compile. I see no problem here.
Nov 17 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 3:57 PM, retard <re tard.com.invalid> wrote:
 Tue, 17 Nov 2009 14:38:57 -0800, Bill Baxter wrote:

 I agree, a tuple of one element (doesn't matter what type, array in
 this case) should be semantically identical to that single element.

 proper semantics for language supported tuples should IMO include: 1)
 syntax to explicitly [de]construct tuples and no auto-flattening 2) a
 tuple of one element is identical to a scalar:
 =A0 int a =3D 5; // scalar integer
 =A0 auto b =3D (5); // tuple of one integer a =3D=3D b // is true

Interesting. =A0It does kinda make sense. =A0So should indexing work too=


 And properties? =A05[0] =3D=3D 5? =A05.length =3D=3D 1? If not that coul=


 for functions that process generic N-tuples. If so then what does that
 do if the "scalar" type happens to be float*?

In some languages () is a distinct Unit type. Tuples are defined recursively from the Pair type, e.g. Pair[int,int], Pair[int, Pair [int,int]] =3D=3D=3D (int,int,int). And have a special indexing syntax wi=

 based indexing.

That wasn't really the question. It was what should 5[0] do in D, if scalars are considered to be 1-tuples? I think that's a killer for 1-tuple / scalar equivalence in D. Neither behavior is acceptable in my opinion. So it seems you can't have 1-tuple/scalar equivalence unless you have a distinct tuple-indexing syntax. Right now std.typecons.tuple uses x.at!(0) because you can't have a x[i] return different types, but the built-in "A..." template tuples do it. So that's something that needs to be fixed anyway, because "good for me but not for thee" is lame. (Took that phrase from a review of Go...) I think probably D should allow a templated opIndex!(int) so that user types can implement tuple-like indexing where each index could be a different type. Or we should try to come up with another syntax for indexing tuples.
 3) function's argument list is a tuple like in ML:
 =A0 void foo(int a, char b);
 =A0 int a =3D 5; char b =3D'a';
 =A0 auto tup =3D (5, 'a');
 =A0 foo(a, b) is identical to foo(t);


Tuples can't encode things like by-ref, by-val, lazy etc.

That does seem to kill that idea.
 That seems like a kind of auto-flattening. =A0Shouldn't (t) be a tuple o=


 a tuple?
 What if you have an actual tuple in the signature, like void foo((int
 a,char b))?
 Or you have both overloads -- foo(int,char) and foo((int,char)) I think
 I like Python's explicit "explode tuple" syntax better.
 =A0 =A0foo(*t)

 Probably that syntax won't work for D, but I'd prefer explicit
 flattening over implicit.

Good boy.
 4) unit type defined by the empty tuple instead of c-like void

This is kind of neat, but does it actually change anything? =A0Or just give an aesthetically pleasing meaning to void/unit?

The empty tuple can be considered to be the unit type.

Yes, Yigal said basically that. The question I have is what practical difference does that make to the language? Seems no different from defining the empty tuple to be void, then renaming void to unit. --bb
Nov 17 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 3:01 PM, Ellery Newcomer
<ellery-newcomer utulsa.edu> wrote:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


That's Python's solution and it seems to work out ok. --bb

How do we express tuple types? ... These won't work: ... (int,int) [] lst; //want

Why won't that work? You may be right, but that particular declaration doesn't seem ambiguous to me. --bb
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
 I agree, a tuple of one element (doesn't matter what type, array in this
 case) should be semantically identical to that single element.

 proper semantics for language supported tuples should IMO include:
 1) syntax to explicitly [de]construct tuples and no auto-flattening
 2) a tuple of one element is identical to a scalar:
 =A0 int a =3D 5; // scalar integer
 =A0 auto b =3D (5); // tuple of one integer
 =A0 a =3D=3D b // is true

Interesting. It does kinda make sense. So should indexing work too? And properties? 5[0] =3D=3D 5? 5.length =3D=3D 1? If not that could be painful for functions that process generic N-tuples. If so then what does that do if the "scalar" type happens to be float*?
 3) function's argument list is a tuple like in ML:
 =A0 void foo(int a, char b);
 =A0 int a =3D 5; char b =3D'a';
 =A0 auto tup =3D (5, 'a');
 =A0 foo(a, b) is identical to foo(t);

That seems like a kind of auto-flattening. Shouldn't (t) be a tuple of a tuple? What if you have an actual tuple in the signature, like void foo((int a,char b))? Or you have both overloads -- foo(int,char) and foo((int,char)) I think I like Python's explicit "explode tuple" syntax better. foo(*t) Probably that syntax won't work for D, but I'd prefer explicit flattening over implicit.
 4) unit type defined by the empty tuple instead of c-like void

This is kind of neat, but does it actually change anything? Or just give an aesthetically pleasing meaning to void/unit? --bb
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Tue, 17 Nov 2009 14:38:57 -0800, Bill Baxter wrote:

 I agree, a tuple of one element (doesn't matter what type, array in
 this case) should be semantically identical to that single element.

 proper semantics for language supported tuples should IMO include: 1)
 syntax to explicitly [de]construct tuples and no auto-flattening 2) a
 tuple of one element is identical to a scalar:
   int a = 5; // scalar integer
   auto b = (5); // tuple of one integer a == b // is true

Interesting. It does kinda make sense. So should indexing work too? And properties? 5[0] == 5? 5.length == 1? If not that could be painful for functions that process generic N-tuples. If so then what does that do if the "scalar" type happens to be float*?

In some languages () is a distinct Unit type. Tuples are defined recursively from the Pair type, e.g. Pair[int,int], Pair[int, Pair [int,int]] === (int,int,int). And have a special indexing syntax with 1- based indexing.
 
 3) function's argument list is a tuple like in ML:
   void foo(int a, char b);
   int a = 5; char b ='a';
   auto tup = (5, 'a');
   foo(a, b) is identical to foo(t);


Tuples can't encode things like by-ref, by-val, lazy etc.
 That seems like a kind of auto-flattening.  Shouldn't (t) be a tuple of
 a tuple?
 What if you have an actual tuple in the signature, like void foo((int
 a,char b))?
 Or you have both overloads -- foo(int,char) and foo((int,char)) I think
 I like Python's explicit "explode tuple" syntax better.
    foo(*t)

 Probably that syntax won't work for D, but I'd prefer explicit
 flattening over implicit.

Good boy.
 
 4) unit type defined by the empty tuple instead of c-like void

This is kind of neat, but does it actually change anything? Or just give an aesthetically pleasing meaning to void/unit?

The empty tuple can be considered to be the unit type.
Nov 17 2009
prev sibling parent Leandro Lucarella <llucax gmail.com> writes:
Ellery Newcomer, el 17 de noviembre a las 17:01 me escribiste:
 Bill Baxter wrote:
 On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

auto a = (i)[0]; what does this do?


That's Python's solution and it seems to work out ok. --bb

How do we express tuple types? Since we have tuple expression syntactic support, we should have tuple type syntactic support. Cuz I'm going to want stuff like Tuple!(int,int) [] lst;

I can live with that, you won't be writing types that often, but I could certainly appreciate a better syntax if we can find one. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Y Gloria Carrá, Gloria Estephan, Gloria Gaynor y Gloria Trevi. -- Peperino Pómoro
Nov 17 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 1:02 PM, Bill Baxter <wbaxter gmail.com> wrote:

 I bet if we search hard enough we can find other examples of bizarre C
 that get interpreted differently by D.

Here's a biggie: the value type fixed-size arrays recently introduced. It aint hard to find examples of C code like this that will now compile, but malfunction, in D: void setValue(float x[4], int el, float val) { x[el] = val; } Yet despite that, the decision was made to go for it because on the whole it's better for the language. --bb
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 11:30 AM, Ellery Newcomer
<ellery-newcomer utulsa.edu> wrote:
 Leandro Lucarella wrote:
 Ellery Newcomer, el 17 de noviembre a las 12:58 me escribiste:
 void fun1(int a);
 void fun1(Tuple!(int,int) a);

 fun1( (a=fizbang(), a+b) );



We agree except for the *easily*. On the contrary, I think it would be extremely rare.

I think by 'easily', I didn't exactly mean 'likely'. Sure it would be rare. Use of comma operator is pretty uncommon itself, from what I've seen (which doesn't include a lot of C code, however). I'm just saying this is one instance where it would cause problems. want another? how about this? int fizzbizz; int* bar; int i = (fizzbizz, bar)[0];

Now *that* looks like a winner. Good one. The last one that required a mix of C and D does not violate the rules. But this one does. However, I think for the good of humanity we can accept that one little bizarre example of legal C syntax not doing the same thing in D. I bet if we search hard enough we can find other examples of bizarre C that get interpreted differently by D. Probably you could concoct something based on the different interpretations of this declaration: int *a, b; I just recalled, though, that the comma operator can be overloaded in C++. What's D's policy on C++ code? --bb
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Thu, 19 Nov 2009 00:00:00 +0200, Yigal Chripun wrote:

 Ellery Newcomer wrote:
   foo(a, b) is identical to foo(t);
 
 does ML have any equivalent of template parameters? eg
 
 foo!(1,int);


 foo's signature is actually: `a -> `a which is like doing in D: T foo(T)
 (T n) { return n + n; } but unlike ML, in D/C++ you need to provide the
 type parameter yourself.
 
 does that answer your question?

A bit more precise answer would be 'no'. ML does not support programming with types directly. There is no way to pass stuff from value world to type world and vice versa like in D.
Nov 19 2009
prev sibling parent retard <re tard.com.invalid> writes:
Thu, 19 Nov 2009 04:11:30 -0500, yigal chripun wrote:

 retard Wrote:
 
 Thu, 19 Nov 2009 00:00:00 +0200, Yigal Chripun wrote:
 
 Ellery Newcomer wrote:
   foo(a, b) is identical to foo(t);
 
 does ML have any equivalent of template parameters? eg
 
 foo!(1,int);


 foo's signature is actually: `a -> `a which is like doing in D: T
 foo(T) (T n) { return n + n; } but unlike ML, in D/C++ you need to
 provide the type parameter yourself.
 
 does that answer your question?

A bit more precise answer would be 'no'. ML does not support programming with types directly. There is no way to pass stuff from value world to type world and vice versa like in D.

I wouldn't say it's a decisive No. there are several extensions to ML like MetaML and MacroML that do have such capabilities. There are also ML inspired languages like Nemerle which provide very powerful AST macro systems.

We were talking about the original Milner's ML, right? If that's not the case, then I agree you're right.
Nov 19 2009
prev sibling next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 
 
 Note that if comma-as-sequencer was removed, and repurposed as a tuple
 literal  (with "a,b"  making a tuple), and if we specify that tuple
 elements are evaluated in order, then I think this would work as a
 replacement for the current comma operator:
 
   (expr1,expr2,expr3)[$-1]
 
 But the nice thing is you can get the effect of a comma operator that
 evaluates to the value of any expression in the sequence, just using
 different indices.
 Not sure how odious people would find forcing an order of eval on
 tuples, though.

I wouldn't mind. you'd also have to swap the precedence of assignment and comma, or a,b = b,a; isn't going to do anything useful. But then you can't have foo(a = b); unless the entire argument list is a tuple. But then you'd have to change {something or another} or you can't have nested tuples. backing up, assuming you don't allow unpareth'd tuples, then what is ( exp ) ? Is it a tuple, or a scalar? I think my personal preference at the moment would be to have tuples of the form (, exp , exp ... )
 
 In the context of a for-loop, you don't care what the value is, so it
 would work as a tuple as-is.  The tuple itself would be the value:
 
   for(; i<10; ++i,++j)  // just works

for should be a special case
Nov 16 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Not sure how odious people would find forcing an order of eval on
 tuples, though.

I've been looking at forcing an order of eval on all expressions. This will improve portability and repeatability. In some experiments I've done, the effect on performance is minimal.
Nov 17 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:

 I've been looking at forcing an order of eval on all expressions. This 
 will improve portability and repeatability. In some experiments I've 
 done, the effect on performance is minimal.

I/we can do some benchmarks... I am curious. But I agree that forcing an order of expression eval is very good. Bye, bearophile
Nov 17 2009
prev sibling next sibling parent Michael Rynn <michaelrynn optusnet.com.au> writes:
On Mon, 16 Nov 2009 18:57:13 -0600, Ellery Newcomer wrote:

 Bill Baxter wrote:
 
 
 Note that if comma-as-sequencer was removed, and repurposed as a tuple
 literal  (with "a,b"  making a tuple), and if we specify that tuple
 elements are evaluated in order, then I think this would work as a
 replacement for the current comma operator:
 
   (expr1,expr2,expr3)[$-1]
 
 But the nice thing is you can get the effect of a comma operator that
 evaluates to the value of any expression in the sequence, just using
 different indices.
 Not sure how odious people would find forcing an order of eval on
 tuples, though.

I wouldn't mind. you'd also have to swap the precedence of assignment and comma, or a,b = b,a; isn't going to do anything useful. But then you can't have foo(a = b); unless the entire argument list is a tuple. But then you'd have to change {something or another} or you can't have nested tuples. backing up, assuming you don't allow unpareth'd tuples, then what is ( exp ) ? Is it a tuple, or a scalar? I think my personal preference at the moment would be to have tuples of the form (, exp , exp ... )
 
 In the context of a for-loop, you don't care what the value is, so it
 would work as a tuple as-is.  The tuple itself would be the value:
 
   for(; i<10; ++i,++j)  // just works

for should be a special case

I read about it in the D Programming Language rough cut draft. 2.4.1 The Comma Operator Expressions separated by commas are evaluated in sequence. The result of the entire expression is the result of the rightmost expression. Example: int a = 5; int b = 10;20 int c = ( a = b, b = 7, 8); After executing the snippet above, the values of a, b, and c are 10, 7, and 8 respectively. Thats all there is! But the expressions may be as complex as you like? Its syntactic sugar folks. Nowhere says you absolutely need it to generate a particular compiled code. But where is the harmful example? Some may want to remove it , in case it can be better used in a future more useful role, or for enforcing source code readability standards. But right now, its in the book! -- michael *^&^*
Nov 17 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Lutger, el 16 de noviembre a las 23:27 me escribiste:
 dsimcha wrote:
 
 == Quote from Lutger (lutger.blijdestijn gmail.com)'s article

 int a = 1;
 int b = --a, ++a;
 assert(b == 1);
 assert(a == 1);

Axe. Looks like the only things it's good for are making code undreadable and abusing for loop syntax to... Make code unreadable. When the heck would this be significantly more readable, safer, or more concise than doing the equivalent without it? Also, from previous discussions I vaguely remember it's constraining other parts of the syntax.

Those discussions were about nice native tuple syntax. The only argument in favor of the comma operator I can remember is code-generation.

Which is a very dumb one. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Y cuando llegamos a nuestro hogar ella saca de su bolsillo derecho un casete de Ricardo Montaner y nos dice: "Ponelo! Ponelo!"; nos desilusionamos un poco, pero a esa altura... Todo da igual. -- Sidharta Kiwi
Nov 17 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Yigal Chripun, el 17 de noviembre a las 07:06 me escribiste:
 Robert Jacques wrote:
On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
<smjg_1998 yahoo.com> wrote:

dsimcha wrote:
<snip>
Axe.  Looks like the only things it's good for are making code
undreadable and
abusing for loop syntax to...
 Make code unreadable.

Suppose you want the increment of a for loop to change two variables in parallel. I don't call that making code unreadable. Stewart.

Yes the classic use case of the comma operator is multi-variable declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a = 0, b = 1; condition(); a++, b++) {...} int a = 0, b = 1 // this is a declaration and not an expression a++, b++ // isn't assigned to any variable and can be treated as a tuple

Exactly, all valid used of the comma operator can still be covered if the comma becomes a tuple literal. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- A heart that's full up like a landfill, a job that slowly kills you, bruises that won't heal.
Nov 17 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:
 
 Great. Sounds like problem solved in that there is no problem.
 
 So how do people feel about bill's suggestion to progress the issue
 further?
 
 Be good to get some comments from higher-up (Walter, Andrei)?
 
 Predict bearophile will chime in on this one too?

The real problem is you'd end up with a tuple syntax identical to a valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- I always get the feeling that when lesbians look at me, they're thinking, '*That's* why I'm not a heterosexual.' -- George Constanza
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 6:06 AM, Leandro Lucarella <llucax gmail.com> wrote:
 Ellery Newcomer, el 16 de noviembre a las 19:02 me escribiste:
 Justin Johansson wrote:

 Great. Sounds like problem solved in that there is no problem.

 So how do people feel about bill's suggestion to progress the issue
 further?

 Be good to get some comments from higher-up (Walter, Andrei)?

 Predict bearophile will chime in on this one too?

The real problem is you'd end up with a tuple syntax identical to a valid c syntax. If D silently accepts it, but does something different, it's a no go.

Code ported from C should not compile if the comma expression is converted to a tuple literal because if a and b are int, typeof(a,b) is int now and will be Tuple!(int, int) in the future, and I don't think a Tuple!(anything) could be implicitly casted to anything, except, maybe, another tuple, but you don't have tuples in C, so there is no risk on that.

Good point! A trick like this: if (ok=func1(), b=func2(), ok) { ... } Will not compile if that's an (int,int,int) tuple. Brilliant. So anywhere you're actually using the value in C is covered, it'll be an error in D. And for places where you're not using the value, it'll do the right thing as long as we define the order of evaluation to be left to right. I think Walter wants to have the evaluation order for most everything defined in D, anyway. Just to avoid having implementation-defined or non-deterministic behavior. --bb
Nov 17 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Ellery Newcomer, el 17 de noviembre a las 12:58 me escribiste:
 Code ported from C should not compile if the comma expression is
 converted
 to a tuple literal because if a and b are int, typeof(a,b) is int now
 and
 will be Tuple!(int, int) in the future, and I don't think
 a Tuple!(anything) could be implicitly casted to anything, except,
 maybe,
 another tuple, but you don't have tuples in C, so there is no risk on
 that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );

These are not code ported from *C*.

all but the second fun1 are, and it could easily exist in D

We agree except for the *easily*. On the contrary, I think it would be extremely rare. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- "CIRILO" Y "SIRACUSA" DE "SEÑORITA MAESTRA": UNO MUERTO Y OTRO PRESO -- Crónica TV
Nov 17 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Leandro Lucarella, el 17 de noviembre a las 16:05 me escribiste:
 Ellery Newcomer, el 17 de noviembre a las 12:58 me escribiste:
 Code ported from C should not compile if the comma expression is
 converted
 to a tuple literal because if a and b are int, typeof(a,b) is int now
 and
 will be Tuple!(int, int) in the future, and I don't think
 a Tuple!(anything) could be implicitly casted to anything, except,
 maybe,
 another tuple, but you don't have tuples in C, so there is no risk on
 that.

void fun1(int a); void fun1(Tuple!(int,int) a); fun1( (a=fizbang(), a+b) );

These are not code ported from *C*.

all but the second fun1 are, and it could easily exist in D

We agree except for the *easily*. On the contrary, I think it would be extremely rare.

And BTW, you introduced a new overload, the same could happen with any type: void fun1(int a); void fun1(double a); int a; double b; fun1( (a=fizbang(), a+b) ); now fun1(double) gets called, and you introduced a bug in the current state of D. So even when this (very rare) problem could exists, it's not introducing by changing the comma operator to be a tuple literal. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Y2K - what a disappointment... i had at least expected one nuclear plant to blow
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 1:51 PM, KennyTM~ <kennytm gmail.com> wrote:
 On Nov 18, 09 05:40, Ellery Newcomer wrote:
 Bill Baxter wrote:
 However, I think for the good of humanity we can accept that one
 little bizarre example of legal C syntax not doing the same thing in
 D.

int[] i; auto a = (i)[0]; what does this do?

(i) should not construct a tuple. Probably (i,).

That's Python's solution and it seems to work out ok. --bb
Nov 17 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 17, 2009 at 2:53 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 17 Nov 2009 15:20:06 -0500, Yigal Chripun <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 11:38:19 -0500, Bill Baxter <wbaxter gmail.com>
 wrote:

 On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford jhu.edu>
 wrote:
 On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line yahoo.de>
 wrote:

 Robert Jacques wrote:
 On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun
 <yigal100 gmail.com>
 wrote:

 Robert Jacques wrote:
 On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
 <smjg_1998 yahoo.com> wrote:

 dsimcha wrote:
 <snip>
 Axe. =A0Looks like the only things it's good for are making cod=











 undreadable and
 abusing for loop syntax to...
 =A0Make code unreadable.

<snip> Suppose you want the increment of a for loop to change two variables in parallel. =A0I don't call that making code unreadable. Stewart.

=A0Yes the classic use case of the comma operator is multi-variab=









 declarations/increments in a for loop.

This was argued before and as I and others said before, this is *not* a use case for the comma separator. e.g. for (int a =3D 0, b =3D 1; condition(); a++, b++) {...} int a =3D 0, b =3D 1 // this is a declaration and not an expressio=








 a++, b++ // isn't assigned to any variable and can be treated as a
 tuple

 the only use case that will break is if the two increments are
 dependent on the order (unless tuples are also evaluated from left
 to
 right):
 e.g.
 a + 5, b + a //

 I doubt it very much that anyone ever uses this, it's too unreadab=








 to be useful.

However, I imagine tuple(a++,b++) would have some overhead, which i=







 exactly what someone is trying to avoid by using custom for loops.

 Personally, I like using a..b =3D> tuple(a,b), since it also solves=







 multi-dimensional slicing and mixed indexing and slicing problems.

Zero overhead. Tuples are flat compile-time entities.

There are compile time tuples and runtime tuples. D already has a for=





 of
 compile-time tuples. This discussion seems to be about runtime tuples
 which
 currently don't have a nice syntax: you have to use tuple(a,b). And
 tuple(a,b) does have runtime overhead.

I think the point is that in something like this: =A0 auto foo =3D (a,b); =A0 foo.a +=3D 2; =A0 foo.b +=3D foo.a; =A0 // etc The tuple foo is allocated on the stack and the compiler knows where the a part and b part are, so the code generated should be absolutely no different from the code generated for: =A0 auto foo_a =3D a; =A0 auto foo_b =3D b; =A0 foo_a +=3D 2; =A0 foo_b +=3D foo_a; =A0 // etc So there doesn't need to be any "tuple overhead". --bb

=A0But that isn't the expansion: for (int a =3D 0, b =3D 1; condition(); a++, b++) =3D> =A0int a =3D 0; int b =3D 0; while(condition) { =A0 =A0auto temp =3D tuple(a++,b++); // creation of a struct on the sta=



 }
 =A0Now the optimizer might get rid of that temporary struct. Then again=



 might not (or its presence interferes with other optimizations). At the=



 least, some amount of code profiling or disassembly needs to be done.

why would it create a struct? it would probably do: int a =3D 0, b =3D 0; while (condition) { =A0 int temp_a =3D (a++); // temp_a =3D=3D a + 1 =A0 int temp_b =3D (b++); } the above would most like be optimized by away. you can also take advantage of tuples with for loops, something like: for ( auto t =3D (0, 0); condition(); (t[1]++, t[2]++) ) {...} this is more flexible since you can't do with the current system: for (int a =3D 0, char b =3D 'a'; ; ) {...} because "int a =3D 0" is a declaration and not an expression. with tuples: for (auto t =3D (0, 'a'); ; ) {...}

*sigh* The reason the compiler would have to create a temporary struct, i=

 because that's what a tuple is at runtime. Tuples need to be compact (lik=

 structs) so that they can be passed to functions, etc.

Sigh back at ya. I think all of us are just assuming that the compiler will be smart enough to realize that the tuple value is not being used and optimize it away. It should be fairly trivial to detect and handle appropriately. At least in the case of that for loop there. I think unused value elimination is probably one of the first things you study in compiler classes on optimization. It must be because even *I* know about it and I've only taken one compiler class that barely touched on optimization at all. :-) --bb
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Tue, 17 Nov 2009 15:04:01 -0800, Bill Baxter wrote:

 On Tue, Nov 17, 2009 at 2:53 PM, Robert Jacques <sandford jhu.edu>
 *sigh* The reason the compiler would have to create a temporary struct,
 is because that's what a tuple is at runtime. Tuples need to be compact
 (like structs) so that they can be passed to functions, etc.

Sigh back at ya. I think all of us are just assuming that the compiler will be smart enough to realize that the tuple value is not being used and optimize it away. It should be fairly trivial to detect and handle appropriately. At least in the case of that for loop there. I think unused value elimination is probably one of the first things you study in compiler classes on optimization. It must be because even *I* know about it and I've only taken one compiler class that barely touched on optimization at all. :-)

Elimination of unused values has been one of the basic optimizations in C compilers for decades. E.g. gcc 4.4 does tremendous amounts of optimizations and the constant folding logic might even optimize away the whole 'for' loop, the function containing the for loop or even the whole object file containing the function. If this kind of argumentation is used against new features, almost every high level feature in D should be shaved off - classes, scope statements, all literals etc. There is a serious amount of extra code those produce compared to a hand crafted asm version of the program.
Nov 17 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 Nov 2009 18:34:32 -0500, retard <re tard.com.invalid> wrote:

 Tue, 17 Nov 2009 15:04:01 -0800, Bill Baxter wrote:

 On Tue, Nov 17, 2009 at 2:53 PM, Robert Jacques <sandford jhu.edu>
 *sigh* The reason the compiler would have to create a temporary struct,
 is because that's what a tuple is at runtime. Tuples need to be compact
 (like structs) so that they can be passed to functions, etc.

Sigh back at ya. I think all of us are just assuming that the compiler will be smart enough to realize that the tuple value is not being used and optimize it away. It should be fairly trivial to detect and handle appropriately. At least in the case of that for loop there. I think unused value elimination is probably one of the first things you study in compiler classes on optimization. It must be because even *I* know about it and I've only taken one compiler class that barely touched on optimization at all. :-)

Elimination of unused values has been one of the basic optimizations in C compilers for decades. E.g. gcc 4.4 does tremendous amounts of optimizations and the constant folding logic might even optimize away the whole 'for' loop, the function containing the for loop or even the whole object file containing the function. If this kind of argumentation is used against new features, almost every high level feature in D should be shaved off - classes, scope statements, all literals etc. There is a serious amount of extra code those produce compared to a hand crafted asm version of the program.

Yes, I know all this. But, before Bill, no-one seemed be cognizant of it (either the optimization or the representation). Also, all those well known optimizations don't magically work for structs: I've seen modern compilers do some pretty stupid things when structs and temporary values are involved.
Nov 17 2009
prev sibling next sibling parent retard <re tard.com.invalid> writes:
Tue, 17 Nov 2009 20:23:35 -0500, Robert Jacques wrote:

 Also, all those well
 known optimizations don't magically work for structs: I've seen modern
 compilers do some pretty stupid things when structs and temporary values
 are involved.

Are you talking about dmc/dmd now? Have you tried gcc 4.4 or 4.5, llvm dev version or latest visual c++ ? Temporary values are often used with e.g. expression templates and the compilers have generated decently performing code for ages now. dmd is the only stupid compiler which cannot inline e.g. expression templates for matrix operations.
Nov 18 2009
prev sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 18 Nov 2009 06:34:59 -0500, retard <re tard.com.invalid> wrote:

 Tue, 17 Nov 2009 20:23:35 -0500, Robert Jacques wrote:

 Also, all those well
 known optimizations don't magically work for structs: I've seen modern
 compilers do some pretty stupid things when structs and temporary values
 are involved.

Are you talking about dmc/dmd now? Have you tried gcc 4.4 or 4.5, llvm dev version or latest visual c++ ? Temporary values are often used with e.g. expression templates and the compilers have generated decently performing code for ages now. dmd is the only stupid compiler which cannot inline e.g. expression templates for matrix operations.

The bug I'm thinking of was in the Open64 compiler, and I think it's been squashed now. But this happened in the last 2-3 years, and only was caught because a major vendor really stressed the performance of struct operations on a particular backend. (Nvidia and GPUs) The point, is that the actual optimization rules in the compiler for free variables and for structs are sometimes completely separate entities. It doesn't mean it can't be done, it just means it might have to be coded. Basically, Tuples introduce a level of obfuscation, which might (or might not) hamper the current optimizer.
Nov 18 2009