Thread overview
"using the result of a comma expression is not allowed"
Apr 21
Don Allen
Apr 21
Dukc
Apr 21
Don Allen
Apr 21
Don Allen
Apr 21
bachmeier
Apr 22
Don Allen
April 21

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.

April 21

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.

April 21

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:

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.

April 21

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

April 21

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

April 21

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.

April 21

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.

April 22
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.
April 22
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.

April 23
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.