• (nodebb)

    You omitted the last line of the article: "To be continued..."

  • (nodebb)

    Annie fixed the code, but admits

    I hope Annie also reverted the change to the CI job settings...

  • LCrawford (unregistered)

    TRWTF is having to read code that says

    if ("success" == data.status)

  • Sauron (unregistered)

    JavaScript is a language that was created to write bugs.

  • DrPepper (unregistered)

    It should be standard practice to write unit tests for code. A couple of unit tests would have caught this error.

  • Dr Spooner built my spear (unregistered)

    When I rule the world, removing error reporting on a linter will be a firing offence.

    In fact, ignoring any compiler warnings will be a firing offence.

    Firing squad offence.

  • Mr Bits (unregistered) in reply to LCrawford

    It took me a while to get used to the "backwards" notation for == comparisons, but adopting the practice has saved me some headaches. I'd rather get used to odd notations than spend late hours chasing obscure bugs.

    And perhaps, as Annie's organization matures, they will start requiring a team review of any CI or static analyzer config changes. Letting a lone developer make such a fundamental change is inviting disaster.

  • (nodebb) in reply to Sauron

    This bug can happen in lots of languages. Basically, all the languages whose syntax is derived from C.

  • WTFGuy (unregistered)

    The linter settings are a management control device. A dev unilaterally changing those is about like finding the dev rifling the boss'es desk during lunch break. Fire immediately upon discovery. Pour encourager les autres.

  • Duke of New York (unregistered)

    There are legitimate uses for an assignment expression as a condition in C-derived languages, including JavaScript. This of course is not one of them.

    Practical example: You want to run a RegExp on a string and do something with the match information if there is one. Since RegExp.exec returns null on no match, and null is falsy, you can use the assignment to a match variable as a branch condition. An extra level of parentheses may help to placate a linter and put readers on notice that the syntax is intended, but it is not necessary. When people object the C tradition of an assignment expression having a value, they are invariably importing assumptions from some other language and not understanding how C was meant to be used.

  • (nodebb) in reply to Barry Margolin

    This bug can happen in lots of languages. Basically, all the languages ~~whose syntax is derived from C~~ that allow type punning.

    There, I fixed it for you.

    Since RegExp.exec returns null on no match, and null is falsy,

    The notion of "falsy" is exactly the problem. It doesn't bother me having to write out if (foo == None) { instead of if (!foo) { if it saves me an hour searching for a difficult to spot 1-character bug.

  • Duke of New York (unregistered)

    It's not a problem if you know how it works. It all comes back to a single principle: know your tools, and don't blame them for being something other than what they are.

  • LCrawford (unregistered) in reply to Duke of New York

    people object the C tradition of an assignment expression having a value, they are invariably importing assumptions from some other language and not understanding how C was meant to be used.

    It's not necessary to allow an assignment in a Boolean test without any compiler warnings, as other languages have showin. In this day it's perfectly reasonable to require breaking out the operation and let the compiler optimize unnecessary operations. Or to require a Pragma that suppresses the statement warning.

  • (nodebb)

    I do find assign-and-test to be a fun, clever trick; and it probably has legitimate uses in a high-performance environment where you can't spare the bytes for a temporary variable. But outside of that, it doesn't seem to be a good habit, because then you can flag assignment in an if as an error and catch bugs before they ever leave your computer.

  • (nodebb)

    There's no excuse nowadays for assign-and-test in any compiled language, as any half decent compiler will optimise away the refetch of the data. I can see some temptation to write if (horrendously-complex-lvalue = a), to avoid typing the monster lvalue twice, but even so, there are ways to deal with that (mostly be sorting out your horrendously-complex-lvalue because you've probably used most of it repeatedly already). And if it's a compiled language, creating a temporary variable holding a reference/pointer to the target will, with a moderately efficient optimiser, not cost any machine code. And it's a hell of a lot easier to understand because you don't hit a wall thinking 'did they mean to assign this? or test it?'

    It's pretty much the same with interpreted languages. And in any case with interpreted language, performance is a different sort of issue.

    The long and the short of this is - write for legibility, not for making the optimisers decisions for it. You'll be grateful when you come back in 3 years.

    and yoda expressions are a crime against legibility.

  • Stuart (unregistered) in reply to thosrtanner

    I'm reminded of the story of the XFree86 project going through and removing every single instance of Duff's Device that they could find. The original Duff's device significantly improved the speed of the code, thanks to it unrolling a loop as well as providing a way to jump into the middle of the loop as necessary.

    The result of removing all those excessively clever switch statements? The code sped up significantly, and the binaries were a lot smaller as well. The optimisation that was so useful back in the 80s is no longer useful, thanks to compilers being much better at those micro-optimisations than humans are, generally speaking.

    The rule now is: start by writing your code, clearly and concisely, using efficient algorithms. Then, if it's too slow, profile the code and look specifically at the slow points. Don't try to micro-optimise early on, because it's practically certain that you'll do it worse than the compiler could (and likely screw up the compiler's ability to do the job into the bargain.)

  • Duke of New York (unregistered)

    I haven't said anything about runtime performance as a reason for writing code one way or another. As far as I care, the compiler should be able to optimize the code in any case. The point is concise idiom.

  • (nodebb)

    Although I code for a living in C-like languages, this is one reason I kinda prefer how Pascal-like languages instead use := for assignment.

  • (nodebb) in reply to staticsan

    More to the point, how the Pascalian ;= doesn't return a value, so it cannot be used in a conditional statement. And that expressions in conditional statements must be of type boolean, with no implicit conversion from non-booleans.

    Addendum 2023-09-21 06:50: Ugh. I meant the Pascalian :=

  • (nodebb) in reply to thosrtanner

    yoda expressions are a crime against legibility

    Not only that, but they only protect the misguided fool that uses them against a narrow subset of possible errors. You can't Yoda this, for example:

         if ( var1 = var2 )
    

    without changing the bug it causes...

    Always always always ask the compiler or linter to error out on "naked" assignments in conditional contexts.

  • (nodebb) in reply to Steve_The_Cynic

    Always always always ask the compiler or linter to error out on "naked" assignments in conditional contexts.

    Which is something C compilers have been doing for years. It doesn't help though, if the dev can go in and change the rules to suppress the warning.

    Making assignment an expression that returns a value may have seemed like a good idea to Ken Thompson, but it has caused no end of problems.

  • (nodebb) in reply to konnichimade

    it probably has legitimate uses in a high-performance environment where you can't spare the bytes for a temporary variable

    In a high-performance environment (i.e., compiled) if (a = foo()) { ... } will generate the exact same assembly asa = foo(); if (a != null) { ... }. The first will get desugared into the second very early in compilation (like the first pass), way before the compiler is anywhere even close to generating assembly. There's no "extra bytes" for a temporary variable; they're all temporaries.

  • Duke of New York (unregistered) in reply to LCrawford

    Your statement is true, but it's also empty, since the negation of it is also true. There is no fundamental reason that assignments must be grammatically distinct from expressions. It's a design choice, just as return and throw expressions are a design choice in Kotlin. Significantly, although JavaScript was based most directly on Java, Eich chose not to follow Java's behavior for conditions but something closer to C's behavior.

  • Officer Johnny Holzkopf (unregistered) in reply to Dr Spooner built my spear

    In addition to running everything compiler-related with mandatory -Wall, all warnings should become errors and thus stopping the compilation process. Furthermore, every program that has been successfully compiled and still spits warnings - yes, I am looking at YOU, mostly all "modern" software! - should be taken out and buried in a core dump. Sadly, nobody seems to care. Silence the error printing, so the errors will be gone. Ignore warnings. Ship faulty software, and promise you will soon offer a fix. For an expensive subscription, of course. Then go shopping.

    JavaScript error: , line 0: uncaught exception: undefined

    (real-world example from an actual program)

  • nasch (unregistered)
    Comment held for moderation.

Leave a comment on “This Equals Success”

Log In or post as a guest

Replying to comment #:

« Return to Article