Jump to page: 1 2 3
Thread overview
D Logic bug
Oct 11, 2018
James Japherson
Oct 11, 2018
rikki cattermole
Oct 11, 2018
krzaq
Oct 11, 2018
Kagamin
Oct 11, 2018
Shachar Shemesh
Oct 11, 2018
Patrick Schluter
Oct 11, 2018
Jonathan Marler
Oct 11, 2018
Jonathan M Davis
Oct 11, 2018
Jonathan Marler
Oct 12, 2018
Jonathan Marler
Oct 12, 2018
Kagamin
Oct 12, 2018
Patrick Schluter
Oct 12, 2018
Patrick Schluter
Oct 15, 2018
Nick Treleaven
Oct 11, 2018
Neia Neutuladh
Oct 11, 2018
Jonathan M Davis
Oct 12, 2018
Patrick Schluter
Oct 12, 2018
Trass3r
October 11, 2018
Took me about an hour to track this one down!

A + (B == 0) ? 0 : C;

D is evaluating it as

(A + (B == 0)) ? 0 : C;


The whole point of the parenthesis was to associate.

I usually explicitly associate precisely because of this!

A + ((B == 0) ? 0 : C);

In the ternary operator it should treat parenthesis directly to the left as the argument.

Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.

October 12, 2018
On 12/10/2018 3:35 AM, James Japherson wrote:
> Took me about an hour to track this one down!
> 
> A + (B == 0) ? 0 : C;
> 
> D is evaluating it as
> 
> (A + (B == 0)) ? 0 : C;
> 
> 
> The whole point of the parenthesis was to associate.
> 
> I usually explicitly associate precisely because of this!
> 
> A + ((B == 0) ? 0 : C);
> 
> In the ternary operator it should treat parenthesis directly to the left as the argument.
> 
> Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.

The specification makes this clear (even if another example is needed).

The conditional expression takes an OrOrExpression not an expression as the condition. In other words, it requires a boolean operation on the left, with Expression's for the branches (deprecated behavior related to assignment for else branch but won't go into that).

So not a bug and is working in a reasonable way.

https://dlang.org/spec/expression.html#conditional_expressions
October 11, 2018
On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson wrote:
> Took me about an hour to track this one down!
>
> A + (B == 0) ? 0 : C;
>
> D is evaluating it as
>
> (A + (B == 0)) ? 0 : C;
>
>
> The whole point of the parenthesis was to associate.
>
> I usually explicitly associate precisely because of this!
>
> A + ((B == 0) ? 0 : C);
>
> In the ternary operator it should treat parenthesis directly to the left as the argument.
>
> Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.

Are any languages evaluating it differently? For example, is this different from C, C++, Java, C#, Ruby, Javascript?
October 11, 2018
On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson wrote:
> In the ternary operator it should treat parenthesis directly to the left as the argument.

I don't think parentheses are ever treated like that. They are self-contained and don't affect operators outside them.
October 11, 2018
On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson wrote:
> Took me about an hour to track this one down!
>
> A + (B == 0) ? 0 : C;
>
> D is evaluating it as
>
> (A + (B == 0)) ? 0 : C;

As it should.

>
>
> The whole point of the parenthesis was to associate.
>
> I usually explicitly associate precisely because of this!
>
> A + ((B == 0) ? 0 : C);
>
> In the ternary operator it should treat parenthesis directly to the left as the argument.
>
> Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.

No. Except for assignement and assignment operators, ternary operator has the lowest precedence of any operator in D (and C, C++, java, PHP, C# etc.).


October 11, 2018
On 11/10/18 20:16, Kagamin wrote:
> On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson wrote:
>> In the ternary operator it should treat parenthesis directly to the left as the argument.
> 
> I don't think parentheses are ever treated like that. They are self-contained and don't affect operators outside them.

Almost.

const(int) *
October 11, 2018
On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson wrote:
> Took me about an hour to track this one down!
>
> A + (B == 0) ? 0 : C;
>
> D is evaluating it as
>
> (A + (B == 0)) ? 0 : C;
>
>
> The whole point of the parenthesis was to associate.
>
> I usually explicitly associate precisely because of this!
>
> A + ((B == 0) ? 0 : C);
>
> In the ternary operator it should treat parenthesis directly to the left as the argument.
>
> Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.

In c++ the ternary operator is the second most lowest precedence operator, just above the comma.  You can see a table of each operator and their precendence here, I refer to it every so often: https://en.cppreference.com/w/cpp/language/operator_precedence

Learning that the ternary operator has such a low precedence is one of those things that all programmers eventually run into...welcome to the club :)

It looks like D has a similar table here (https://wiki.dlang.org/Operator_precedence).  However, it doesn't appear to have the ternary operator in there. On that note, D would take it's precedence order from C/C++ unless there's a VERY good reason to change it.
October 11, 2018
On 10/11/2018 07:35 AM, James Japherson wrote:
> Took me about an hour to track this one down!
> 
> A + (B == 0) ? 0 : C;
> 
> D is evaluating it as
> 
> (A + (B == 0)) ? 0 : C;

Friends don't let friends use the ternary operator except in trivial cases.

This would be a good thing for a linter to check.

> The whole point of the parenthesis was to associate.

Yes. The expression would otherwise have been parsed as:

((A + B) == 0) ? 0 : C

It might be a good idea to deprecate arithmetic with booleans, which would have caught this specific error.
October 11, 2018
On Thursday, October 11, 2018 1:09:14 PM MDT Jonathan Marler via Digitalmars-d wrote:
> On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson
>
> wrote:
> > Took me about an hour to track this one down!
> >
> > A + (B == 0) ? 0 : C;
> >
> > D is evaluating it as
> >
> > (A + (B == 0)) ? 0 : C;
> >
> >
> > The whole point of the parenthesis was to associate.
> >
> > I usually explicitly associate precisely because of this!
> >
> > A + ((B == 0) ? 0 : C);
> >
> > In the ternary operator it should treat parenthesis directly to the left as the argument.
> >
> > Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.
>
> In c++ the ternary operator is the second most lowest precedence operator, just above the comma.  You can see a table of each operator and their precendence here, I refer to it every so often: https://en.cppreference.com/w/cpp/language/operator_precedence
>
> Learning that the ternary operator has such a low precedence is one of those things that all programmers eventually run into...welcome to the club :)
>
> It looks like D has a similar table here (https://wiki.dlang.org/Operator_precedence).  However, it doesn't appear to have the ternary operator in there. On that note, D would take it's precedence order from C/C++ unless there's a VERY good reason to change it.

The operator precedence matches in D. Because in principle, C code should either be valid D code with the same semantics as it had in C, or it shouldn't compile as D code, changing operator precedence isn't something that D is going to do (though clearly, the ternary operator needs to be added to the table). It would be a disaster for porting code if we did.

- Jonathan M Davis



October 11, 2018
On Thursday, 11 October 2018 at 21:57:00 UTC, Jonathan M Davis wrote:
> On Thursday, October 11, 2018 1:09:14 PM MDT Jonathan Marler via Digitalmars-d wrote:
>> On Thursday, 11 October 2018 at 14:35:34 UTC, James Japherson
>>
>> wrote:
>> > Took me about an hour to track this one down!
>> >
>> > A + (B == 0) ? 0 : C;
>> >
>> > D is evaluating it as
>> >
>> > (A + (B == 0)) ? 0 : C;
>> >
>> >
>> > The whole point of the parenthesis was to associate.
>> >
>> > I usually explicitly associate precisely because of this!
>> >
>> > A + ((B == 0) ? 0 : C);
>> >
>> > In the ternary operator it should treat parenthesis directly to the left as the argument.
>> >
>> > Of course, I doubt this will get fixed but it should be noted so other don't step in the same poo.
>>
>> In c++ the ternary operator is the second most lowest precedence operator, just above the comma.  You can see a table of each operator and their precendence here, I refer to it every so often: https://en.cppreference.com/w/cpp/language/operator_precedence
>>
>> Learning that the ternary operator has such a low precedence is one of those things that all programmers eventually run into...welcome to the club :)
>>
>> It looks like D has a similar table here (https://wiki.dlang.org/Operator_precedence).  However, it doesn't appear to have the ternary operator in there. On that note, D would take it's precedence order from C/C++ unless there's a VERY good reason to change it.
>
> The operator precedence matches in D. Because in principle, C code should either be valid D code with the same semantics as it had in C, or it shouldn't compile as D code, changing operator precedence isn't something that D is going to do (though clearly, the ternary operator needs to be added to the table). It would be a disaster for porting code if we did.
>
> - Jonathan M Davis

I had a look at the table again, looks like the ternary operator is on there, just called the "conditional operator".  And to clarify, D's operator precedence is close to C/C++ but doesn't match exactly.  This is likely a result of the grammar differences rather than an intention one.  For example, the "Conditional operator" in D actually has a higher priority than an assignment, but in C++ it's the same and is evaluated right-to-left.  So this expression would be different in C++ and D:

a ? b : c = d

In D it would be:

(a ? b : c ) = d

And in C++ would be:

a ? b : (c = d)

Check it out:

---
import core.stdc.stdio;
void main()
{
    int a = 2, b = 3;
    printf("expr = %d\n", 1 ? a : b = 4);
}
---
prints "expr = 4"

it evaluates the conditional (1 ? a : b) into the expression a, which is actually an rvalue! and then assigns it to 4 because of the "= 4" and then returns the value 4 to printf.

Here's the C++ version:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int a = 2, b = 3;
    printf("expr = %d\n", 1 ? a : b = 4);
}

This one prints "expr = 2"

It simply returns the value of `a` because the "b = 4" at the end is all part of the "else" contition in the ternary operator.

« First   ‹ Prev
1 2 3