April 07, 2018
On 04/07/2018 02:07 AM, sdvcn wrote:
>      string stt = "none";
>      true?writeln("AA"):writeln("BB");   ///Out:AA
>          true?stt="AA":stt="BB";    <<<<-----///Out:BB
>      writeln(stt);

It is a bug because the behavior does not match the spec:

  https://issues.dlang.org/show_bug.cgi?id=18743

Ali
April 07, 2018
On Saturday, 7 April 2018 at 14:28:05 UTC, kdevel wrote:
> On Saturday, 7 April 2018 at 09:56:43 UTC, Jonathan M Davis wrote:
>>>          true?stt="AA":stt="BB";    <<<<-----///Out:BB
>
> [...]
>
>> Assignment takes precendence over the ternary operator.
>
> That's not true. Not in D and not in C/C++

The odd man out is C++ [1], assignment has higher precedence because of right to left evaluation. Do not mix it with C please. All other C derived languages have indeed higher precedence for ternary than assignment: C [2], java [3], C# [4] and D [5].

[1]: http://en.cppreference.com/w/cpp/language/operator_precedence
[2]: http://en.cppreference.com/w/c/language/operator_precedence
[3]: https://introcs.cs.princeton.edu/java/11precedence/
[4]: https://www.tutorialspoint.com/csharp/csharp_operators_precedence.htm
[5]: https://wiki.dlang.org/Operator_precedence

> https://wiki.dlang.org/Operator_precedence
> http://en.cppreference.com/w/c/language/operator_precedence#cite_note-2
>
>> So, no, I don't think that it is. Putting parens around the assignment expressions makes it print AA.
>
> It should not matter if there are parens around the assignment.
>
>> As it stands, it evaluates both assignment expressions before evaluating the ternary operator.
>
> That is not true in C/C++, let me quote from a C standard (draft), § 6.1.5 conditional operator:

Stop mixing C with C++ they are really 2 very different beasts (one is a programming language, the other is Cthulu :-)

<snip>
April 07, 2018
On Saturday, 7 April 2018 at 15:26:56 UTC, Ali Çehreli wrote:
> On 04/07/2018 02:07 AM, sdvcn wrote:
>>      string stt = "none";
>>      true?writeln("AA"):writeln("BB");   ///Out:AA
>>          true?stt="AA":stt="BB";    <<<<-----///Out:BB
>>      writeln(stt);
>
> It is a bug because the behavior does not match the spec:
>
>   https://issues.dlang.org/show_bug.cgi?id=18743
>
> Ali

Hi Ali C

I think it also a bug because the ternary seem to be returning the second part

try

    string stt = "none";
    string b = "";
    true?writeln("AA"):writeln("BB");   ///Out:AA
    b = (true ? stt="AA":stt="BB");    ///Out:BB
    writeln(stt);
    writeln(b); ///Out:BB
April 07, 2018
On 04/07/2018 10:53 AM, Ali wrote:
> On Saturday, 7 April 2018 at 15:26:56 UTC, Ali Çehreli wrote:
>> On 04/07/2018 02:07 AM, sdvcn wrote:
>>>      string stt = "none";
>>>      true?writeln("AA"):writeln("BB");   ///Out:AA
>>>          true?stt="AA":stt="BB";    <<<<-----///Out:BB
>>>      writeln(stt);
>>
>> It is a bug because the behavior does not match the spec:
>>
>>   https://issues.dlang.org/show_bug.cgi?id=18743
>>
>> Ali
>
> Hi Ali C
>
> I think it also a bug because the ternary seem to be returning the
> second part

Maybe... but the following is not a good test for that because the return value of the assignment operator would always be stt regardless of which expression is evaluated.

>
> try
>
>      string stt = "none";
>      string b = "";
>      true?writeln("AA"):writeln("BB");   ///Out:AA
>      b = (true ? stt="AA":stt="BB");    ///Out:BB
>      writeln(stt);
>      writeln(b); ///Out:BB

I tried something else and noticed that it doesn't actually evaluate the third expression because b is never changed:

import std.stdio;

void main() {
    int a;
    int b;
    int * c = &(true ? a = 1 : b = 2);
    writefln("a:%s %s", a, &a);
    writefln("b:%s %s", b, &b);
    writefln("c:  %s", c);
}

Output:

a:2 7FFDBBF57DB0  <-- Got the value of the third expression (BAD)
b:0 7FFDBBF57DB4  <-- Not changed (good)
c:  7FFDBBF57DB0  <-- Address of a (good)

So, the expression correctly decides to affect and returns 'a' but uses the wrong value to assign.

Ali

April 07, 2018
On Saturday, 7 April 2018 at 18:52:56 UTC, Ali Çehreli wrote:
> On 04/07/2018 10:53 AM, Ali wrote:
> > On Saturday, 7 April 2018 at 15:26:56 UTC, Ali Çehreli wrote:
> >> On 04/07/2018 02:07 AM, sdvcn wrote:
> >>>      string stt = "none";
> >>>      true?writeln("AA"):writeln("BB");   ///Out:AA
> >>>          true?stt="AA":stt="BB";    <<<<-----///Out:BB
> >>>      writeln(stt);
> >>
> >> It is a bug because the behavior does not match the spec:
> >>
> >>   https://issues.dlang.org/show_bug.cgi?id=18743
> >>
> >> Ali
> >
> > Hi Ali C
> >
> > I think it also a bug because the ternary seem to be
> returning the
> > second part
>
> Maybe... but the following is not a good test for that because the return value of the assignment operator would always be stt regardless of which expression is evaluated.
>
> >
> > try
> >
> >      string stt = "none";
> >      string b = "";
> >      true?writeln("AA"):writeln("BB");   ///Out:AA
> >      b = (true ? stt="AA":stt="BB");    ///Out:BB
> >      writeln(stt);
> >      writeln(b); ///Out:BB
>
> I tried something else and noticed that it doesn't actually evaluate the third expression because b is never changed:
>
> import std.stdio;
>
> void main() {
>     int a;
>     int b;
>     int * c = &(true ? a = 1 : b = 2);
>     writefln("a:%s %s", a, &a);
>     writefln("b:%s %s", b, &b);
>     writefln("c:  %s", c);
> }
>
> Output:
>
> a:2 7FFDBBF57DB0  <-- Got the value of the third expression (BAD)
> b:0 7FFDBBF57DB4  <-- Not changed (good)
> c:  7FFDBBF57DB0  <-- Address of a (good)
>
> So, the expression correctly decides to affect and returns 'a' but uses the wrong value to assign.
>
> Ali

this kinda explains what happens to me
try
    string stt = "none";
    string b = "";
    true?writeln("AA"):writeln("BB");
    b = (true ? stt="AA": stt )="BB";
    writeln(stt);
    writeln(b);

output
AA
BB
BB

now try

    string stt = "none";
    string b = "";
    true?writeln("AA"):writeln("BB");   ///Out:AA
    (b = (true ? stt="AA": stt ))="BB";    ///Out:BB
    writeln(stt);
    writeln(b);

output
AA
AA
BB

so it seems
that since
    b = (true ? stt="AA": stt )="BB";
and
    b = true ? stt="AA": stt ="BB";

are equivalent
that

that the ternary operator return stt (after assigning it "AA") then assign "BB" to it


April 07, 2018
On Saturday, 7 April 2018 at 16:52:00 UTC, Patrick Schluter wrote:
[...]
> The odd man out is C++ [1], assignment has higher precedence because of right to left evaluation.

Your reference [1] is not even a witness to your claim. The precedence table says that the "Ternary conditional" has the *same* precedence as the "Direct Assigment", namely "16".

You may find an in-depth discussion of the C++ case in

https://stackoverflow.com/questions/7499400/ternary-conditional-and-assignment-operator-precedence
April 07, 2018
On Saturday, 7 April 2018 at 19:44:35 UTC, Ali wrote:
> so it seems
> that since
>     b = (true ? stt="AA": stt )="BB";
> and
>     b = true ? stt="AA": stt ="BB";
>
> are equivalent
> that
>
> that the ternary operator return stt (after assigning it "AA") then assign "BB" to it

Can the ternary conditional even be used to assign objects of the wrong type?

dcondo.d
---
import std.stdio;

class A {
   int a;
   this (int i)
   {
      a = i;
   }
}

class C {
   int c;
   this (int i)
   {
      c = i;
   }
}

void dump (A a, A b, C c, C d)
{
   a.writeln;
   b.writeln;
   c.writeln;
   d.writeln;
   a.a.writeln;
   b.a.writeln;
   c.c.writeln;
   d.c.writeln;
}

void main ()
{
   A a = new A (1), b = new A (2);
   C c = new C (3), d = new C (4);
   dump (a, b, c, d);
   true ? a = b : c = d;
//   a = c; // Error: cannot implicitly convert expression
//   c = a; // Error: cannot implicitly convert expression
   dump (a, b, c, d);
}
---

Output:

dcondo.A
dcondo.A
dcondo.C
dcondo.C
1
2
3
4
dcondo.C
dcondo.A
dcondo.C
dcondo.C
4
2
3
4

April 07, 2018
On Saturday, 7 April 2018 at 21:22:07 UTC, kdevel wrote:
> Can the ternary conditional even be used to assign objects of the wrong type?
> […]

Congratulations, I'm pretty sure you found an actual bug, even though it doesn't have anything to do with the conditional operator per se: https://issues.dlang.org/show_bug.cgi?id=18744

 — David
April 07, 2018
On Saturday, 7 April 2018 at 09:07:48 UTC, sdvcn wrote:
>         true?stt="AA":stt="BB";    <<<<-----///Out:BB
> 	writeln(stt);

As I just pointed out in Ali's bug report [1], this is correct, as

    true ? stt = "AA" : stt = "BB"

means

    (true ? (stt = "AA") : stt) = "BB",

in accordance to D's grammar [2]:

AssignExpression:
    ConditionalExpression
    ConditionalExpression = AssignExpression
    […]

We should probably require explicit parentheses here. Relying on this behaviour is just asking for trouble anyway, as evidenced by the amount of confusion in this thread.

 — David



[1] https://issues.dlang.org/show_bug.cgi?id=18743
[2] https://dlang.org/spec/expression.html#assign_expressions
April 08, 2018
On Saturday, 7 April 2018 at 20:57:23 UTC, kdevel wrote:
> On Saturday, 7 April 2018 at 16:52:00 UTC, Patrick Schluter wrote:
> [...]
>> The odd man out is C++ [1], assignment has higher precedence because of right to left evaluation.
>
> Your reference [1] is not even a witness to your claim. The precedence table says that the "Ternary conditional" has the *same* precedence as the "Direct Assigment", namely "16".
>
> You may find an in-depth discussion of the C++ case in
>
> https://stackoverflow.com/questions/7499400/ternary-conditional-and-assignment-operator-precedence

My formulation was ambiguous, it is the same precedence as the link says. The link also says that's it's right to left evaluation. This means that for expression:

    a ? b = c : d = e;


right to left evaluation will make the = e assignment higher priority than the b = c assignment or the ternary even if they have the same priority level. The operative word was the right to left but granted I could have formulated it better.