• P (unregistered)

    This WTF is miles away from being a good WTF.

  • LCrawford (unregistered)

    I can't wait to see the frist WTF for a run-on ternary using the "spaceship operator" <=> for a grand orgy of decisions on a single line.

  • bvs23bkv33 (unregistered)

    are they going to start seliing those mile trimmers in wallmart anytime soon?

  • Legacy Warrior (unregistered)

    I get frustrated at how often the noble ternary operator is maligned here on TDWTF. "It's hard to read" is a weak argument and says more about a code base's style and formatting guidelines than the operator itself. (Although a requisite on nice formatting could be constructed as an argument against ternaries.) But even with a nasty nested ternary, I can abstract the code as "well, we're just setting the value of a single variable" (maybe even without side effects!) whereas I always have to second-guess if the nested if-if-if-else-else-if-else-else pyramid block has other flow control or business logic snuck into it. Just my limited 2c

  • (nodebb)

    DUH-duh-duh-duh!

  • Sally Flynn (unregistered)

    It's not often I get a laugh out of these articles (as I usually end up wanting a triple vodka to dull the pain of the code I just saw), but the rewritten song lyrics at the end got a good chuckle out of me :D

  • Foo AKA Fooo (unregistered) in reply to Legacy Warrior

    Your point about abstracting the code is exactly what I keep saying! And the same goes while writing the code. I cannot accidentally forget to set the variable in one branch, or accidentally set another variable in one branch (especially if there are similarly named variables, like here), I cannot accidentally forget the final "else" branch, etc.

    Also, I can set the variable on declaration (as is done here). There's no point where the variable is unset, so a whole class of problems is avoided. (And this goes for languages like C/C++ that actually leave unset variables undefined, just as well as for other languages that set them to 0, null, unset, etc. because those are still invalid values in this context.)

    The main issues with ternaries seem to come down to 3 things:

    1. overuse/abuse (but that can be done with any feature)

    2. unfamiliarity (which leads to avoiding them which leads to remaining unfamiliar with them -- vicious cycle)

    3. bad formatting (on this site, this may be in the original code or introduced by the editors in an effort of "look how long this line is" / "look how ridiculous those ternaries look"); if I knew without guessing how to insert a code block here (i.e., if the markup accepted was documented), I'd post a more readable version of the given code; now I won't but you can believe me it's possible.

  • Legacy Warrior (unregistered) in reply to Foo AKA Fooo

    yeah, i forgot to mention the benefit of avoiding uninitialized values. this lets you use the super-cool 'const' keyword in some languages! I usually format my ternaries with the '?' and the ':' on a new line and indented. this japes the readability of (potentially nested) if-else blocks. but if a ternary (or any block of code) gets too unwieldy, refactoring it into a separate method/function can prove useful (and improve unit-test-ability!)

  • (nodebb)

    This HAS to be someone on my team here at work. This is par for the course here.

  • doubting_poster (unregistered) in reply to lordofduct

    easy enough to check, do a text search over the codebase ;)

  • Argle (unregistered)

    Two Irishmen are strolling through a graveyard reading headstones. "'ere now, this fellow Sean from Kilkenny lived to be 87." "Aye, and Seamus from Swinford lived to be 98." "Good heavens! This fellow lived to be 120." "120? That's nae possible. Who is it?" "Miles from Dublin."

  • (nodebb) in reply to doubting_poster

    I could, but that takes effort.

  • ooOOooGa (unregistered)

    My only beef with the ternary operator (aside from the various forms of abuse mentioned already) is that it is named "'the' ternary operator".

    We have a small pile of unary operators such as increment, decrement, and dereference. We have a large pile of binary operators: addition, subtraction, array index, ...

    But because the ternary operator is simply called "'the' ternary operator" it causes resistance to ever adding any other 3-argument operators to a language. Because if there was more than one ternary operator, what would we call "'the' ternary operator"?

  • TruePony (unregistered)

    I now understand the appeal of expression-valued if-then-else blocks

  • (nodebb)

    Strongly in favor of the ternary here, also especially in combination with a const keyword. It allows things like

    const color = deposit > 0 ? GREEN :
                  deposit < 0 ? RED :
                  BLACK;
    

    I less like the version of python though. For such simple tabular cases, using

    color = ( GREEN if deposit > 0 else
              RED   if deposit < 0 else
              BLACK )
    

    works well enough, if not better than the C-style ternary, but somehow I find it awkward to have the value on the left side. Probably mostly because it messes in weird ways with the order of evaluation...

    # C-style:                     Evaluation-Order
    result = a() ? b() :
             c() ? d() :           a, b, c, d, e 
             e()
    # Python-Style:
    result = ( a() if b() else
               c() if d() else     b, a, d, c, e
               e() )
    
  • Calli Arcale (unregistered)

    And I would write five hundred lines and I would write five hundred more just to be the man who wrote a thousand lines Uncaught Exception at line 24

    This is gold. It absolutely slew me. :-P

  • Officer Johnny Holzkopf (unregistered) in reply to ooOOooGa

    The "arity classes" discussed are: unary, binary, ternary. The operators belonging to those classes have a name each, such as increment operator, dereference operator (unary), multiplication operator, logical AND operator (binary), and lo and behold: conditional operator (ternary). An option is the term decision operator (german: Entscheidungsoperator) which was its common name in older german C programming material, whereas the correct translation probably would have been bedingter Operator ("conditional" = bedingt). Maybe this depends on the time when and where the material was written...

  • FristName LastName (unregistered)

    I always thought that the ternary operator was nothing more than syntactic sugar for an if statement. What am I missing?

  • David Mårtensson (unregistered) in reply to FristName LastName

    A ternary operator is part of an expression, and always returns a value.

    An if, depending on language, often cannot return a value and in most does not enforce an else so only the true branch exist.

    Some languages allow ifs to return a value but then there is always some else, either explicit or implicit (null or default).

    So in some languages it can be just syntactic sugar, but in others its most definitely its own construct.

  • WTFGuy (unregistered)

    @FristName LastName: If you take the view that all higher level languages are just "syntactic sugar" for machine code, then yes, it's just a sugared if statement.

    But usually the term "syntactic sugar" is reserved for much smaller ideas; two ways of saying exactly the same thing with exactly the same limitatons, one just shorter than the other. e.g. in C# all three of these forms are exactly equivalent sematically:

    SomeBizObject myObject = new SomeBizObject(); // traditional and verbose
    var myObject = new SomeBizObject(); // less verbose; compiler intuits the type of the right half expression and applies that to the left side variable name myObject = new SomeBizObject(); // shortest, but only works when right side is a new operator

    There are several critical differences between the conditional operator (?) and an if statement:

    1. An if statement need not have an else; a conditional operator always has an else.
    2. An if statement can contain an arbitrarily large block of code that cannot return a value. A conditional operator always returns a value. How large a block of code you can squeeze into a conditional (and therefore how many side effects they may have), is at least partly limited by the requirement to return a value.

    There's nothing preventing you from having a conditional operator expression that looks something like bool success = bizObject.SomeProperty == magicValue ? GiganticFunctionWithLotsofSideEffects1(BizObject) : GiganticOtherFunctionWithLotsofSideEffects2(BizObject)
    But that represents a clear and obvious abuse of the intended purpose of the conditional operator.

    Which is to evaluate one of two relatively simple expressions yielding a single value of a single type and assign that value (or object reference) to the value of the entire expression. For best style, the expressions to be evaluated should not have side effects. That's not a matter of language restriction, but rather one of style for understandability, testability, and maintainability.

  • WTFGuy (unregistered)

    Acch! I fouled up the markdown AND I was ninja'd by David Mårtensson. Oh well.

  • FristName LastName (unregistered) in reply to David Mårtensson

    Thank you and @WTFGuy for enlightening me. I wasn't aware of all the finer points, although the business of the return value eventually did occur to me--long after posting. You guys are great. I'm glad I asked.

  • I'm not a robot (unregistered) in reply to ooOOooGa
    My only beef with the ternary operator (aside from the various forms of abuse mentioned already) is that it is named "'the' ternary operator".
    ... except it isn't, at least in:

    C https://en.cppreference.com/w/c/language/operator_other#Conditional_operator C++ https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator Java https://docs.oracle.com/javase/specs/jls/se13/html/jls-15.html#jls-15.25 C# https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#conditional-operator JavaScript https://www.ecma-international.org/ecma-262/10.0/index.html#sec-conditional-operator Perl https://perldoc.perl.org/perlop.html#Conditional-Operator Python https://docs.python.org/3/reference/expressions.html#conditional-expressions

    All of those call it the "conditional operator" or a "conditional expression" (with C# and Python acknowledging "ternary operator" as something that it's "at times also called" or "sometimes called", rather than its actual name).

    (For the record I also checked Ruby, which calls it "ternary if" (https://docs.ruby-lang.org/en/2.6.0/syntax/control_expressions_rdoc.html#label-Ternary+if) and PHP, which does indeed use "ternary operator" (https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary) - but who cares what PHP thinks?)

  • (nodebb)

    The Real WTF is using Nullable<bool>. They should have used a proper tri-state enum like everyone else:

    https://thedailywtf.com/articles/What_Is_Truth_0x3f_

  • Ternary King (unregistered) in reply to Legacy Warrior

    I agree with you. However disgusting a ternary (and tbh a two level one doesn't qualify as a WTF for me), at least these lines are clearly "string VariableName = {expression that returns string}", and unless I'm trying to debug that actual value, I don't really care what is in the expression. (Now, if you're calling methods in a ternary that have side effects, that is a WTF.) If you have a stack of 10 lines of flow control instead then I have to read all of those to see if they do something I care about.

    The WTF here is (i) formatting - three conditions with values of that length should be on at least two lines, imo, and (ii) the logic (why take the first 2 characters of a longer number) which would be the same either way.

  • Rutland Gizz (unregistered)

    Good to see casual racism alive and well on the internet. Who knew?

  • Tgape (unregistered) in reply to WTFGuy

    You seem to have missed the limit that, at least in many languages, the conditional operator is part of a statement, so cannot include any statement separators inside it, nor can it contain any blocks or keywords that operate on blocks. This is a significant limiter of abuse, although it's not flawless.

    (To be clear: in all languages I'm familiar with, the conditional operator or inline if [whichever the language has] is part of a statement. What varies is whether or not one can have multiple statements inside it anyway, and whether or not one can have loops, ifs, and other code blocks inside it.)

    Also, just for the record, there are some languages where the conditional operator can refrain from returning a value.

    my $foo = $flag ? 12 : return;

Leave a comment on “Trim Off a Few Miles”

Log In or post as a guest

Replying to comment #508536:

« Return to Article