Thread overview
Disallowing ?:?: syntax
Jan 05, 2009
bearophile
Jan 05, 2009
Stewart Gordon
Jan 05, 2009
Miles
Jan 05, 2009
Nick Sabalausky
Jan 05, 2009
Miles
Jan 05, 2009
BCS
Jan 05, 2009
Miles
Jan 05, 2009
BCS
January 05, 2009
Where the operation isn't no symmetric, all binary operators (but assignment) in C are left-associative. But x?y:z is right-associative, so:

x ? y : a ? b : c

is:

x ? y : (a ? b : c)

My little proposal for D is to turn the following into a syntax error, to avoid possile programmer mistakes (so the programmer must put parentheses here to make it compile):

x ? y : a ? b : c

If it becomes a syntax error, then it's better if the error message tells to put how to fix generic code, for example:

"x ? y : a ? b : c  ==> x ? y : (a ? b : c)"

Bye,
bearophile
January 05, 2009
bearophile wrote:
<snip>
> My little proposal for D is to turn the following into a syntax error, to avoid possile programmer mistakes (so the programmer must put parentheses here to make it compile):
> 
> x ? y : a ? b : c
<snip>

Here, right-associativity is intuitive - it's analogous to if-then-elseif.  So it should probably still be allowed.

IMO if there's anywhere where parentheses should be required, it's on the confusing combinations of bitwise and relational operators.

Stewart.
January 05, 2009
bearophile wrote:
> My little proposal for D is to turn the following into a syntax error, to avoid possile programmer mistakes (so the programmer must put parentheses here to make it compile):
> 
> x ? y : a ? b : c

The ternary operator is not ambiguous, I see no need for making it an error. I have used such constructs very often, with no problem:

writefln("Printer is %s.",
	 status == OFFLINE      ? "offline"      :
	 status == ONLINE       ? "online"       :
	 status == CHECK        ? "out of paper" :
	 status == ONLINE_CHECK ? "on fire"      :
	 "unknown status");

That would become a real mess of parenthesis.
January 05, 2009
"Miles" <_______@_______.____> wrote in message news:gjst46$2hh1$1@digitalmars.com...
> bearophile wrote:
>> My little proposal for D is to turn the following into a syntax error, to avoid possile programmer mistakes (so the programmer must put parentheses here to make it compile):
>>
>> x ? y : a ? b : c
>
> The ternary operator is not ambiguous, I see no need for making it an error. I have used such constructs very often, with no problem:
>
> writefln("Printer is %s.",
> status == OFFLINE      ? "offline"      :
> status == ONLINE       ? "online"       :
> status == CHECK        ? "out of paper" :
> status == ONLINE_CHECK ? "on fire"      :
> "unknown status");
>
> That would become a real mess of parenthesis.

This makes my highly DRY-oriented mind think:

While ?: is an expression-based counterpart to the statement-based if...else, maybe we could use a similar expression-based counterpart to switch? (I think I've seen such a thing in hardware description languages)

--------------------
writefln("Printer is %s.",
status ??   // Purely illustrative syntax
OFFLINE => "offline" ::
ONLINE => "online" ::
CHECK => "out of paper" ::
ONLINE_CHECK => "on fire" ::
default => "unknown status");
--------------------

Although, I've often created re-usable lookup tables to handle that sort of thing:

--------------------
char[] getPrinterStatusStr(uint code)
{
    // Somthing like this, I forget the exact syntax and nuances. D's array
literals are a PITA.
    char[][uint] printerStatusCodeToStr =
    [
        OFFLINE : "offline",
        ONLINE : "online",
        CHECK : "out of paper",
        ONLINE_CHECK : "on fire",
    ];

    return (code in printerStatusCodeToStr)?
        printerStatusCodeToStr[code] :
        "unknown status";
}
writefln("Printer is %s.", getPrinterStatusStr(status));
--------------------

But the ??=>:: (again, purely illustrative syntax) would be a nice alternative to have at my disposal. And it would make writing getPrinterStatusStr much nicer.

Back to the original ?:?: issue: If I were to ever chain ?:'s, Miles's example above is the only time I ever would feel comfortable omitting any disambiguating parens. If we got a ??=>:: (or something like it), then I would agree with making ?:?: illegal without disambiguating parens. But without a ??=>::, I think Miles's example provides a compelling reason to keep the ?:?:.


January 05, 2009
Reply to Miles,

> bearophile wrote:
> 
>> My little proposal for D is to turn the following into a syntax
>> error, to avoid possile programmer mistakes (so the programmer must
>> put parentheses here to make it compile):
>> 
>> x ? y : a ? b : c
>> 
> The ternary operator is not ambiguous,

I think not.

x ? y : a ? b : c => (x ? y : a) ? b : c

or

x ? y : a ? b : c => x ? y : (a ? b : c)


without checking the actual syntax you can't tell which of the above will be used and (according to bearophile) if ?: followed after +/-/etc the first would be.

> I see no need for making it an
> error. I have used such constructs very often, with no problem:
> 

However I agree. Don't change it.

> writefln("Printer is %s.",
> status == OFFLINE      ? "offline"      :
> status == ONLINE       ? "online"       :
> status == CHECK        ? "out of paper" :

> status == ONLINE_CHECK ? "on fire"      :

ha ha ha :)

> "unknown status");
> That would become a real mess of parenthesis.
> 


January 05, 2009
Nick Sabalausky wrote:
> This makes my highly DRY-oriented mind think:
> 
> While ?: is an expression-based counterpart to the statement-based if...else, maybe we could use a similar expression-based counterpart to switch? (I think I've seen such a thing in hardware description languages)

I think I have seen that using a mixture of recursive templates and lazy evaluation. But sure, that would be a nice addition to support a relatively common use-case.

Two things I miss are the ?: GNU C extension ( a ?: b  expands to  a ? a
: b , except that a is evaluated only once) or the ?? C# construct
(similar idea, but only tests for null reference).
January 05, 2009
BCS wrote:
> I think not.
> 
> x ? y : a ? b : c => (x ? y : a) ? b : c
> 
> or
> 
> x ? y : a ? b : c => x ? y : (a ? b : c)
> 
> without checking the actual syntax you can't tell which of the above will be used and (according to bearophile) if ?: followed after +/-/etc the first would be.

It simply can't be the first, due to the kind of parser used for C and most of its derived languages (D included). When a '?' is found, the parser recurses until it finds a ':' (it gets stuck in a branch of the syntax tree until a colon token is found).

This is in how the language is defined
(http://www.digitalmars.com/d/2.0/expression.html):

	ConditionalExpression:
		OrOrExpression
		OrOrExpression ? Expression : ConditionalExpression

So, the third operand to the ternary operator is a ConditionalExpression itself, the parser have no reason to finish this evaluation branch if it finds another '?', it naturally recurses.

So, x ? y : a ? b : c => x ? y : (a ? b : c).

But I think that I know what kind of ambiguity you are talking about now... For me, ambiguity is something like the <...> C++ template definition/instantiation operator, or the function declaration/object variable definition ambiguity.
January 05, 2009
Reply to Miles,

> BCS wrote:
> 
>> I think not.
>> 
>> x ? y : a ? b : c => (x ? y : a) ? b : c
>> 
>> or
>> 
>> x ? y : a ? b : c => x ? y : (a ? b : c)
>> 
>> without checking the actual syntax you can't tell which of the above
>> will be used and (according to bearophile) if ?: followed after
>> +/-/etc the first would be.
>> 
> It simply can't be the first, due to the kind of parser used for C and
> most of its derived languages (D included). When a '?' is found, the
> parser recurses until it finds a ':' (it gets stuck in a branch of the
> syntax tree until a colon token is found).
> 
> This is in how the language is defined
> (http://www.digitalmars.com/d/2.0/expression.html):
>   ConditionalExpression:
>      OrOrExpression
>      OrOrExpression ? Expression : ConditionalExpression
> So, the third operand to the ternary operator is a
> ConditionalExpression itself, the parser have no reason to finish this
> evaluation branch if it finds another '?', it naturally recurses.
> 
> So, x ? y : a ? b : c => x ? y : (a ? b : c).
> 

You have just proven my exact point. To find how it parses you need to dig up the syntax, as you just did (Note I said that you can't tell how it's parsed *without* doing that).

Also note that most (or all) of the other operators in C/C++/C#/D/etc go the other way:

OrOrExpression:
  AndAndExpression
  OrOrExpression || AndAndExpression

> But I think that I know what kind of ambiguity you are talking about
> now... For me, ambiguity is something like the <...> C++ template
> definition/instantiation operator, or the function declaration/object
> variable definition ambiguity.
> 

Yes, I think you've spotted the point. I'm referring to ambiguities that will cause problems with <joke>I-BAL</joke> type parsers.