• Bob (unregistered)

    Is it just me, or could that "if" be a ternary?

  • (nodebb) in reply to Bob

    Yes.

  • (nodebb)

    Hahaha Python ternaries are in a different order. Rewriting it in Python is a puzzle for the ages.

  • 🤷 (unregistered)

    Just waiting for someone to explain that this really isn't a WTF, and that it might have a practical purpose in embedded systems.

  • Aspie Architect (unregistered)

    Planetary sterilisation pattern number 5!

  • mihi (unregistered)

    The side effects are quite easy to factor out:

    // xGrad or yGrad with larger / smaller absolute value
    		float maxGrad, minGrad; 
    		if (Math.abs(xGrad) >= Math.abs(yGrad)) {
    			maxGrad = xGrad; minGrad = yGrad;
    		} else {
    			maxGrad = yGrad; minGrad = xGrad;
    		}
    		
    		// now we can assign tmp once and for all
    		tmp = Math.abs(maxGrad * gradMag);
    

    Then you can replace xGrad and yGrad by maxGrad or minGrad in the remaining expressions, and use normal "extract variables" and "convert ternary to if" in your favourite IDE to clean up the code to a point where there are no repeated ifs and no ternaries remaining.

    But when looking at the final code, there are either some constraints about the sign of xGrad and yGrad (which would make the code much simpler when done properly) or there are about half of the cases missing... If the business case is clear (some tests of a 2D point lying outside some range?) probably it is safer to nuke and rewrite.

  • Johan Kaewberg (unregistered)

    Ternary tyrrany. I so hate people who write complex boolean expressions in terms of ternaries.. Break the condition into simple, reasonable named variables, then combine those (in a regular if)

  • Foo AKA Fooo (unregistered)

    Well, the "side effects" are just setting a temporary variable which (I hope!) is only used within the condition. Sure, it would have been better to set two temporaries before (which also avoids some code repetition), but it's still an order of MAGNITUDE_SCALE less bad than external side-effects within a condition.

    What also irks me is ">=" vs. ">". Since this is floating-point apparently, this either indicates general sloppiness or they really think there's a meaningful difference. I noticed this because, if both were ">=" (or both ">"), they could replace "(tmp = exp) >= a && tmp >= b" with "exp >= max (a, b)", also avoiding the temporaries.

  • sizer99 (google)

    I think that's the first time I've ever seen someone number their ternary depth in the comments. Normally you should not have to do that, ever, because you would never do a ternary deeper than 1, or with great shame and greater parens sneak in a simple 2.

    And usually when you get someone insane to do a 4-deep (5 if you count the if), they're too crazy to do something as helpful/sane as numbering them to keep track of where the hell you are. So this was someone dumb enough to do the four deep (plus if), but had a glimmer of awareness about the badness of it... or maybe another person came in later and was afraid to touch it to clean it up but added the numbering.

  • JJ (unregistered)

    It amazes me how many devs think nested ternaries are bad, but see nothing wrong with nested if-else. Down to formatting, I guess. Format ternaries like if-else, and they're just as easy to read, ternaries are just shorthand.

  • groz (unregistered) in reply to sizer99

    Properly formatted nested ternaries work quite well for dispatch table-like conditional assignment.

    See https://thedailywtf.com/articles/comments/Turn_it_up_to_Eleven#comment-118865

    Not sure what the auteur of this tangle was thinking when he wrote it though

  • EmbeddedSpree (unregistered)

    I don't see what is inherently wrong with the assignment to tmp. Assuming that it is reasonably scoped (as its name suggests), it's performing exactly the same role as the parameter to a lambda function in an expression such as (tmp) => { return abs(tmp); } The tmp serves a purpose for common sub-expresion elimination (as another has pointed out, that should be taken further) and for debugging.

    There's also nothing wrong with using >=. Floating-point numbers are sometimes equal. And there's not much in this snippet to suggest the variables are floating-point anyway, except for the telltale (float) 1 at the top (which would be better expressed as 0.0F). At the bottom, the assignment is for integer (fixed-point) arithmetic, so there is quite likely a mix of integer and floating point variables here.

    I agree the whole thing could be simplified by refactoring. That's a fairly normal affair. Move on, nothing to see here...

  • Foo AKA Fooo (unregistered) in reply to groz

    Of course, properly formatted ternaries work fine, even nested to some degree. I use them a lot myself, very similar to the linked code.

    But on this site, that's a taboo. Ternaries are bad by axiom, and any evidence such as today's code is welcome, even unrelated WTFs that happen to contain a ternary.

    Often the main problem is indeed just formatting, and sometimes good formatting is prevented by overly strict formatting rules that forbid additional whitespace for "tabular" layout or enforce line breaks in unsuitable places. So the ternary operator must be to blame.

  • EmbeddedSpree (unregistered) in reply to mihi

    As far as the quadrants, I would guess that "nMag", "neMag", "eMag", "seMag", "sMag", "swMag", "wMag" and "nwMag" are magnifications along a given point of the compass. (Which makes the code work for octants...) Why someone would want eight different variables for holding a 2D magnification is more of a puzzle.

  • EmbeddedSpree (unregistered) in reply to Foo AKA Fooo

    Indeed, I think were the ternary operator syntax to use words such as, say, "if-else" instead of "? :" there would be fewer complaints. For that to work, you'd need the result of an if-statement be the result of the branch taken, and the result of a compound-statement be the result of the last statement executed: that is, make all statements be expressions and have some set of rules for type conversion when the different sides of the branch return different types (as are defined in C++ for ?:). (Although there's no obvious result of a loop-statement.)

    I can't see why a five-line if/else to set a narrowly-scoped variable is inherently clearer than a one-line ternary statement, and a ?: is the better way if you want the conditionally-defined variable to be const (in C++).

  • Dave, from Oz (unregistered)

    This is C, not Java. In java, assignment is not an operator that can be used as part of an expression.

  • LegacyWarrior (unregistered)

    Normally I'm in favor of ternaries but even this made me feel a little queasy. The place I draw the line is when side effects occur within them. Know when and where to use your tools appropriately.

  • (nodebb)

    Guessing this started out as a "simple" if or two, then the author thought of another case and just stuck in another ternary, then thought of another case, so stuck in another....

    ternaries all the way down.

  • sizer99 (google) in reply to groz

    Is this for languages where you don't actually have a switch statement?

  • Runoratsu (unregistered) in reply to Johan Kaewberg

    I agree! My team lead always scolds me when I fix stuff like that, tho. „That’s just YOUR style. You can’t rewrite other people’s code unless you absolutely need to change the behaviour! If you don‘t, you just have to learn to read THIS style of code—all the others can do it, too!“. Same with functions with multiple in-out parameters (so ones not always set when entering the function, not always set when exiting the function, and influencing the behaviour inside the function). Or ones thousands of lines long with conditionals, loops and returns often >10 layers deep, etc. 🤮

  • Ulli (unregistered)

    My Wtf starts with the type cast in the first line: if (xGrad * yGrad <= (float) 0. Just compare against 0 and let the compiler do its job.

  • (nodebb)

    xGrad appears to be East and yGrad appears to be South, so for instance the first case which handles the octants NE..E and SW..W compares xGrad*gradMag against yGrad*(neMag-eMag)-xGrad*eMag and yGrad*(swMag-wMag)+xGrad*wMag, while the other octants might switch xGrad with yGrad, might switch neMag and swMag with nwMag and seMag, might switch eMag and wMag with nMag and sMag, and might switch + for -; I haven't worked out the logic behind that.

  • The Ternary King (unregistered) in reply to groz

    Properly formatted nested ternaries work quite well for dispatch table-like conditional assignment

    Yes, I find that easier to read than the equivalent if/else tree or a switch/case, particularly if you're returning a value. But that's not nested in any sense other than the semantically pedantic - it's logically (and written as) a set of 8 options at the same level. Actual nested ternaries, where both branches contain ternaries like in the OP, generally are a WTF.

    Though of course TRWTF here is not assigning the final outcome in a single massive ternary.

    And the real real WTF is that I suspect Python, like PHP, has a different opinion on the precedence of ternaries versus other stuff.

Leave a comment on “Tern Java Into Python”

Log In or post as a guest

Replying to comment #:

« Return to Article