www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "using the result of a comma expression is not allowed"

reply Don Allen <donaldcallen gmail.com> writes:
I just ran across "using the result of a comma expression is not 
allowed" in a situation where I used a comma expression as I 
would in C, expecting its value to be the value of the right-most 
expression.

While D's language document is accurate in explaining how the 
comma expression is treated in D in 11.5, that treatment 
conflicts with 11.1:
"Expressions are used to compute values with a resulting type. 
These values can then be assigned, tested, or ignored. 
Expressions can also have side effects."

This restriction makes no sense to me, nor does calling this an 
"expression" if you can't use its value.
Apr 21
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Sunday, 21 April 2024 at 16:28:47 UTC, Don Allen wrote:
 I just ran across "using the result of a comma expression is 
 not allowed" in a situation where I used a comma expression as 
 I would in C, expecting its value to be the value of the 
 right-most expression.

 While D's language document is accurate in explaining how the 
 comma expression is treated in D in 11.5, that treatment 
 conflicts with 11.1:
 "Expressions are used to compute values with a resulting type. 
 These values can then be assigned, tested, or ignored. 
 Expressions can also have side effects."

 This restriction makes no sense to me, nor does calling this an 
 "expression" if you can't use its value.
IIRC the rationale here was to reserve the comma operator for use in tuple expressions (like in Python). If you the behavior of a C-style comma expression, you can use a function literal: // `e1, e2` becomes () { e1; return e2; }() If `e2` is an lvalue, you may want to prefix the function literal with `ref`.
Apr 21
prev sibling next sibling parent Dukc <ajieskola gmail.com> writes:
On Sunday, 21 April 2024 at 16:28:47 UTC, Don Allen wrote:
 I just ran across "using the result of a comma expression is 
 not allowed" in a situation where I used a comma expression as 
 I would in C, expecting its value to be the value of the 
 right-most expression.

 While D's language document is accurate in explaining how the 
 comma expression is treated in D in 11.5, that treatment 
 conflicts with 11.1:
 "Expressions are used to compute values with a resulting type. 
 These values can then be assigned, tested, or ignored. 
 Expressions can also have side effects."

 This restriction makes no sense to me, nor does calling this an 
 "expression" if you can't use its value.
The comma expression used to work just like in C several years ago. Using it's value was disallowed at some point because there have been talks about using the syntax for something else - tuples if I recall correctly. The idea was that this way we don't end up changing what a syntax does overnight, it will be disabled for a few years in between so there can be a deprecation period. Apparently the spec wasn't corrected completely to reflect the new rules. It is an expression in a grammatical sense, meaning you can put a comma expression anywhere you would put a side-effecting expression. For example: ```D for(;;comma(), expression()) condition? another(), comma(), expression(): (yet(), another(), expression()); ``` ...well it seems the compiler rejects the conditional here (otherwise this is fine). That's arguably a bug, after all it's not using the result in any way.
Apr 21
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Sunday, 21 April 2024 at 16:28:47 UTC, Don Allen wrote:
 I just ran across "using the result of a comma expression is 
 not allowed" in a situation where I used a comma expression as 
 I would in C, expecting its value to be the value of the 
 right-most expression.

 While D's language document is accurate in explaining how the 
 comma expression is treated in D in 11.5, that treatment 
 conflicts with 11.1:
 "Expressions are used to compute values with a resulting type. 
 These values can then be assigned, tested, or ignored. 
 Expressions can also have side effects."

 This restriction makes no sense to me, nor does calling this an 
 "expression" if you can't use its value.
Comma expressions can make code with typos be accepted causing confusing problems. The compromise, since comma expressions are useful in the update section of `for` loops, was to simply disallow using the value of the expression. In my experience with C, by far the most common use of comma expressions is to expand macros in expression context. Obviously, we don't need that in D, you can do the same thing with a lambda in D. A very notorious misuse of comma expressions was in Andrei's "The D Programming Language" book, where it was stated that `synchronized(A, B)` would protect the following block by locking `A` and `B` in the proper sequence. However, this feature was not implemented, instead, `A, B` was a comma expression, and only `B` was locked. As also noted by others, we may reuse the comma expression syntax for tuples somehow, which only works if you can't use comma expressions to mean "only the last thing". -Steve
Apr 21
parent reply Don Allen <donaldcallen gmail.com> writes:
Thank you both for your useful replies and I understand why D has 
parted company with C in this area.

But I maintain that the documentation is in conflict with itself 
and should be fixed (11.1 could note that there are exceptions, 
such as comma expressions). And I think it's bad practice to 
support a hobbled version of a common construct in anticipation 
of a use of the same syntax that hasn't happened yet and has been 
in the pipeline for years.

I am also not about to re-write my code using lambdas. It's 
hackish workaround for a defect in the language, in my opinion.

And this whole discussion brings up the issue, for me, that 'if' 
and blocks are not expressions that can yield values. Both Rust 
and Zig support this. The separate and redundant conditional 
statement and expression in D is a holdover from C. I think this 
was a mistake in C and a bigger mistake in D, since we know more 
now about language design than when Dennis Ritchie designed C 
about 55 years ago.

On Sunday, 21 April 2024 at 18:31:55 UTC, Steven Schveighoffer 
wrote:
 On Sunday, 21 April 2024 at 16:28:47 UTC, Don Allen wrote:
 I just ran across "using the result of a comma expression is 
 not allowed" in a situation where I used a comma expression as 
 I would in C, expecting its value to be the value of the 
 right-most expression.

 While D's language document is accurate in explaining how the 
 comma expression is treated in D in 11.5, that treatment 
 conflicts with 11.1:
 "Expressions are used to compute values with a resulting type. 
 These values can then be assigned, tested, or ignored. 
 Expressions can also have side effects."

 This restriction makes no sense to me, nor does calling this 
 an "expression" if you can't use its value.
Comma expressions can make code with typos be accepted causing confusing problems. The compromise, since comma expressions are useful in the update section of `for` loops, was to simply disallow using the value of the expression. In my experience with C, by far the most common use of comma expressions is to expand macros in expression context. Obviously, we don't need that in D, you can do the same thing with a lambda in D. A very notorious misuse of comma expressions was in Andrei's "The D Programming Language" book, where it was stated that `synchronized(A, B)` would protect the following block by locking `A` and `B` in the proper sequence. However, this feature was not implemented, instead, `A, B` was a comma expression, and only `B` was locked. As also noted by others, we may reuse the comma expression syntax for tuples somehow, which only works if you can't use comma expressions to mean "only the last thing". -Steve
Apr 21
next sibling parent Don Allen <donaldcallen gmail.com> writes:
On Sunday, 21 April 2024 at 19:16:03 UTC, Don Allen wrote:
 Thank you both for your useful replies and I understand why D 
 has parted company with C in this area.

 But I maintain that the documentation is in conflict with 
 itself and should be fixed (11.1 could note that there are 
 exceptions, such as comma expressions). And I think it's bad 
 practice to support a hobbled version of a common construct in 
 anticipation of a use of the same syntax that hasn't happened 
 yet and has been in the pipeline for years.

 I am also not about to re-write my code using lambdas. It's 
 hackish workaround for a defect in the language, in my opinion.
I should have noted that I am not talking about lambdas in general -- just as a substitute in this instance for blocks returning values. I have written a lot of Lisp and Scheme over many years.
Apr 21
prev sibling next sibling parent bachmeier <no spam.net> writes:
On Sunday, 21 April 2024 at 19:16:03 UTC, Don Allen wrote:

 And this whole discussion brings up the issue, for me, that 
 'if' and blocks are not expressions that can yield values. Both 
 Rust and Zig support this. The separate and redundant 
 conditional statement and expression in D is a holdover from C. 
 I think this was a mistake in C and a bigger mistake in D, 
 since we know more now about language design than when Dennis 
 Ritchie designed C about 55 years ago.
I agree, and it's more than just those two languages, so I view this as a small barrier to D. It's one of those things that might not be major, but it does get annoying.
Apr 21
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 4/21/24 21:16, Don Allen wrote:
 And I think it's bad practice to support a hobbled version of a common
construct in anticipation of a use of the same syntax that hasn't happened yet
and has been in the pipeline for years.
That is just one part of the rationale (that is probably on top of people's mind now as there has been some recent movement on tuples). https://dlang.org/deprecate#Using%20the%20result%20of%20a%20comma%20expression In any case, I don't understand why you focus on the tuple use case. The main reason the comma operator was restricted was to avoid accidental uses. Freeing up the syntax for something that is actually useful is just a nice side effect.
 I am also not about to re-write my code using lambdas. It's hackish workaround
for a defect in the language, in my opinion.
There are many ways to write any given piece of code and the variant with the comma operator is hardly ever the best one.
 I think this was a mistake in C and a bigger mistake in D, since we know 
 more now about language design than when Dennis Ritchie designed C about 
 55 years ago.
One of the things we know now is that comma expressions were a bad design of syntax. We should probably just have something like `let statement in expression` expressions instead.
Apr 21
parent reply Don Allen <donaldcallen gmail.com> writes:
On Sunday, 21 April 2024 at 23:32:21 UTC, Timon Gehr wrote:
 On 4/21/24 21:16, Don Allen wrote:
 And I think it's bad practice to support a hobbled version of 
 a common construct in anticipation of a use of the same syntax 
 that hasn't happened yet and has been in the pipeline for 
 years.
That is just one part of the rationale (that is probably on top of people's mind now as there has been some recent movement on tuples). https://dlang.org/deprecate#Using%20the%20result%20of%20a%20comma%20expression In any case, I don't understand why you focus on the tuple use case.
Excuse me. I am an ordinary user of D (you know, the kinds of people the project would like to attract? One way to torpedo that is to behave like an OpenBSD developer), not someone who has participated in, or followed the history of, the language's development. I focused on tuples because it came up repeatedly in the responses to my original post. You note that yourself above. So I don't understand why you didn't understand. The main reason the comma operator was restricted was to
 avoid accidental uses. Freeing up the syntax for something that 
 is actually useful is just a nice side effect.

 I am also not about to re-write my code using lambdas. It's 
 hackish workaround for a defect in the language, in my opinion.
There are many ways to write any given piece of code and the variant with the comma operator is hardly ever the best one.
You haven't seen the situation where I attempted to use it as I would have in C, have you?
 I think this was a mistake in C and a bigger mistake in D, 
 since we know more now about language design than when Dennis 
 Ritchie designed C about 55 years ago.
One of the things we know now is that comma expressions were a bad design of syntax. We should probably just have something like `let statement in expression` expressions instead.
You may have missed my point, which was that value-returning block expressions are a better way than comma expressions to allow multi-statement sequences to provide a value, as in Rust: ```` let foo:i64 = if predicate { stmta1; stmta2; expra1 } else { stmtb1; stmtb2; exprb1 }; ```` Something similar exists in Zig, though I don't think their syntax is as elegant as Rust's in this case.
Apr 22
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 4/22/24 15:21, Don Allen wrote:
 On Sunday, 21 April 2024 at 23:32:21 UTC, Timon Gehr wrote:
 On 4/21/24 21:16, Don Allen wrote:
 And I think it's bad practice to support a hobbled version of a 
 common construct in anticipation of a use of the same syntax that 
 hasn't happened yet and has been in the pipeline for years.
That is just one part of the rationale (that is probably on top of people's mind now as there has been some recent movement on tuples). https://dlang.org/deprecate#Using%20the%20result%20of%20a%20comma%20expression In any case, I don't understand why you focus on the tuple use case.
Excuse me. ...
No offense had been taken.
 I focused on tuples because 
 it came up repeatedly in the responses to my original post. You note 
 that yourself above. So I don't understand why you didn't understand.
 ...
Because your response was to a post that gave a more nuanced and more complete answer, with the proper weight given to the different arguments.
 ...

 There are many ways to write any given piece of code and the variant 
 with the comma operator is hardly ever the best one.
You haven't seen the situation where I attempted to use it as I would have in C, have you? ...
Feel free to share.
 I think this was a mistake in C and a bigger mistake in D, since we 
 know more now about language design than when Dennis Ritchie designed 
 C about 55 years ago.
One of the things we know now is that comma expressions were a bad design of syntax. We should probably just have something like `let statement in expression` expressions instead.
You may have missed my point,
I did not.
 which was that value-returning block 
 expressions are a better way than comma expressions to allow 
 multi-statement sequences to provide a value, as in Rust:
 
 ````
 let foo:i64 = if predicate
                {
                 stmta1;
                 stmta2;
                 expra1
                }
                else
                {
                 stmtb1;
                 stmtb2;
                 exprb1
                };
 ````
 Something similar exists in Zig, though I don't think their syntax is as 
 elegant as Rust's in this case.
 
This does not clash with tuple syntax.
Apr 22