http://www.perlmonks.org?node_id=587242


in reply to ?: = Obfuscation?

If you want consensus on this one, don't ask more than one language designer. :-)

From a language design point of view, there are certainly some problems with ?:, some of which have been pointed out here. Our approach in Perl 6 has been to try to fix the problems without throwing out the whole idea. One of the problems is simply that it's too hard to see the bits of ?:, so we made the bits bigger. In Perl 6 you use ??!! instead. This also plays into the Perl 6 principle that ? and ! are generally preferred to ask whether things are true or false. There is no natural association between : and the concept of falseness.

But what is the basic idea of ?: anyway? I think it's there to avoid doing extra assignments. You'll notice all the workarounds involve repeating your destination variable, which violates the "don't repeat yourself" principle, aka the DRY principle. So if that's the basic purpose of ?:, and if we teach people that that's the basic purpose of ?:, then people won't be tempted to write things like:

$huh ? $x = 42 : $x = 43;
So education is part of it. But the language can do a little more work for you here, and in fact, if in Perl 6 you say
$huh ?? $x = 42 !! $x = 43;
it will give you a syntax error (though pugs doesn't do this correctly yet). What's really going on here is that the Perl 5 compiler is ignoring the precedence of ?: in the middle, as if you had written:
$huh ? ( $x = 42 ) : $x = 43;

Perl 6 will not supply the implicit parens there, so if you use any operator with a precedence looser than ??!! in the middle, you'll get a missing !! error. This will catch 90% of the bogus uses of the ternary operator, and help teach people that it doesn't mix well with embedded assignment. It doesn't help with a bogus assignment on the right, of course, but usually that error is caught by the fact that most ternary operators do not return a legal lvalue.

Any existing language will give you lots of features in a take-it-or-leave-it way, and Perl 5 is no exception. So it's tempting to try to come up with a simple answer to the question of whether a particular feature is good or evil. Often the answer is "It depends." And when that's the answer, it is often an indication that the feature could benefit from a redesign. When you start thinking about it that way, you start to find you can't just think about the one feature in isolation. You start to think that maybe this applies at all different scales to many of the features in Perl 5, and that the fix for one feature often involves fixing a different feature in parallel. And that's the short answer to why we are working on Perl 6.

Replies are listed 'Best First'.
Re^2: ?: = Obfuscation?
by ysth (Canon) on Dec 01, 2006 at 18:49 UTC
    If you want consensus on this one, don't ask more than one language designer.
    And even asking one is risky.
Re^2: ?: = Obfuscation?
by Melly (Chaplain) on Dec 01, 2006 at 19:21 UTC

    Interesting - and the Perl 6 changes make sense (although they lengthen the golf-courses for everyone ;).

    I noticed the point about the implicit parens between ? and : when I was writing a related tutorial, but just sort of shrugged it off - it seemed reasonable (since '?' implies a closing ':'), but in some ways confusing (since you are more likely to be confused by the behaviour of $x?$y=1:$y=0).

    I intend to revise and improve the tutorial to try and reflect some of the views expressed in this thread, but without swamping the users for whom the tutorial is written with too many distractions.

    BTW do you think, with acknowledgements, it's ok to use code from this thread in the tutorial, or is it polite to ask the individual contributors first?

    map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
    Tom Melly, pm@tomandlu.co.uk
      I like ?: when the args are short.

      I spent years as a LISP programmer. A programmer who has memorized the precedence table will write code that's understandable by others who have memorized the precedence table. Use parenthesis liberally.

      $longways = $widthIsLonger ? $width || 1 : $height || 1;
      may work and is terse, but
      $longways = $widthIsLonger ? ($width || 1) : ($height || 1);
      reads better to me.

      It's mostly the case that if I'm using an operator within the scope of ?: I'll parenthesize.

Re^2: ?: = Obfuscation?
by blazar (Canon) on Dec 02, 2006 at 13:28 UTC
    From a language design point of view, there are certainly some problems with ?:, some of which have been pointed out here. Our approach in Perl 6 has been to try to fix the problems without throwing out the whole idea. One of the problems is simply that it's too hard to see the bits of ?:, so we made the bits bigger. In Perl 6 you use ??!! instead. This also plays into the Perl 6 principle that ? and ! are generally preferred to ask whether things are true or false. There is no natural association between : and the concept of falseness.

    Speaking of the ternary operator (whatever it' spelt), I've sometimes felt the need to make it... ehm... quaternary. Specifically, in cases in which I wanted it to return something different on true, false (but defined) and undefined first argument respectively. Now, before pointing out that there are ways around, let me tell you that I know there are tons in Perl 5 and presumably even more so in Perl 6. But I'd also like a syntactically sweet enough solution out of the box, and I wondered whether an optional <c<!!</c> may trigger that:

    my $wanted = $cond ?? $true !! $false !! $undefined;