www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What is a "comma expression"?

reply rempas <rempas tutanota.com> writes:
This is the first time I'm finding something like that. I'm 
having the following code in C:

```
   if (0 == (i >> 7)) {
     if (len < 1) return -1;
     v = i;
     return *ret = v, 1;
   }
```

This is part of a function that returns an `int`. When I'm 
running this in C, it works. However in D, I'm getting the 
following error message:

```
Error: Using the result of a comma expression is not allowed
```

Can someone explain what comma expressions are and why they don't 
work in D (or if the only doesn't work as returned values from a 
function)?
Oct 10 2021
next sibling parent reply Elmar <chrehme gmx.de> writes:
On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote:
 This is the first time I'm finding something like that. I'm 
 having the following code in C:

 ```
   if (0 == (i >> 7)) {
     if (len < 1) return -1;
     v = i;
     return *ret = v, 1;
   }
 ```

 This is part of a function that returns an `int`. When I'm 
 running this in C, it works. However in D, I'm getting the 
 following error message:

 ```
 Error: Using the result of a comma expression is not allowed
 ```

 Can someone explain what comma expressions are and why they 
 don't work in D (or if the only doesn't work as returned values 
 from a function)?
Hello rempas. The comma-operator `,` is like `;` but results in an expression value, not a statement like `;` would. The left side of `,` is executed like a statement and the value of the right side of `,` is returned. Comma-expressions are merely used to pack additional instructions into places where only expressions are allowed. ```d if (x = y, myNiceFunction(), yay(x), x > 5) { // ... } ``` or ```d if (hasFancyFunkyStuff) x = z, fancy(x), funkyUpdate(z); // too lazy for braces ``` Many consider the `,` operator to be a design-flaw because it makes expressions difficult to read and can be easily abused because the above should actually be: ```d x = y; myNiceFunction(); yay(x); if (x > 5) { // ... } ``` In `D` you can still write the second example of code but not the first example of code. The designers of D thought they could make it less painful by just forbidding comma-expressions to be used as expression value and only as statement. This is because then comma-expressions can still be used in `for`-loops: ```d for (x = y, z = a; x < z; x++, z--) { ; } ``` In conclusion, your C snippet should actually look like: ```c if (0 == (i >> 7)) { if (len < 1) return -1; *ret = v = i; return 1; } ``` The previous snippet even could mislead readers to think that it would return a tuple of two elements which it doesn't.
Oct 10 2021
parent rempas <rempas tutanota.com> writes:
On Sunday, 10 October 2021 at 12:13:47 UTC, Elmar wrote:
 Hello rempas.

 The comma-operator `,` is like `;` but results in an expression 
 value, not a statement like `;` would. The left side of `,` is 
 executed like a statement and the value of the right side of 
 `,` is returned. Comma-expressions are merely used to pack 
 additional instructions into places where only expressions are 
 allowed.

 [...]
Thanks, that's the second time you are helping me today!
Oct 10 2021
prev sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote:
     return *ret = v, 1;
The comma expression in C is a combination of two things but in the context of another thing. Well that's not very good, but like there's statements and expressions. Statements do something but do not have a value. So `if() {}` and `return` and `for() {}` are statements, because they don't have a value you can assign to a variable. Expressions do something but DO have a value and thus you can assign it to a variable. a = if (true) { a } ; // not permitted because if is a statement a = 5 + 4; // OK, 5+4 is an expression and thus has a value This is a slight simplification but generally true. You'll notice in some languages the if assign does work; in those languages you have an if expression rather than an if statement. The language grammar has rules for where statements are allowed and where expressions are allowed and you can't mix and match (unless the grammar has two rules, one allowing each type). Anyway, the C comma expression is a combination of two other expressions where the first one is evaluated, but its value discarded, then the second part becomes the value of the whole expression. a = 1, 2; // the 1 is discarded, so a == 2 It is actually the same as writing out: 1; // evaluate this then discard it a = 2; // eval this and actually keep the value The difference being that it is allowed in an expression context. So that `return *ret = v, 1;` Could just be written *ret = v; // this is eval'ed and value discarded return 1; // second part value is kept And idk why they didn't just do that here. But the C thing is most commonly seen in a for loop: for(a = 0, b = 0; a < 5; a++, b++) {} because the grammar only allows an expression in each piece of the for loop, so you can't separate the two steps by semicolons like you do in different contexts.
 Can someone explain what comma expressions are and why they 
 don't work in D (or if the only doesn't work as returned values 
 from a function)?
D considers it a bit obscure and special-case to use the comma for. There was talk a while ago about making the comma do something else instead, but this never materialized. But you can always write it out longer form, perhaps wrapping it in a function. // what I would do here: *ret = v; return 1; // or if you absolutely had to have it in an expression context: return (){ *ret = v; return 1; }(); The nested function there explicitly does what the comma operator does and is allowed in expression context as well.
Oct 10 2021
parent rempas <rempas tutanota.com> writes:
On Sunday, 10 October 2021 at 12:19:39 UTC, Adam D Ruppe wrote:
 On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote:
     [...]
The comma expression in C is a combination of two things but in the context of another thing. Well that's not very good, but like there's statements and expressions. Statements do something but do not have a value. So `if() {}` and `return` and `for() {}` are statements, because they don't have a value you can assign to a variable. [...]
Thanks a lot for the detailed explanation! Have a nice day!
Oct 10 2021