• smlckz@programming.dev
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    20 hours ago

    Option C. The value NaN compares unequal to every value, even itself. This breaks one of the rules of what equality even means (that every value must be equal to itself, the “reflexivity” axiom). It is for this reason (among others, equality “partial” equivalence between values of different types? 🤮) Rust needed to have PartialEq. See IEEE 754 for more details.

    Why typeof null is "object"? Because it is defined so: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-typeof-operator

    5. If val is null, return "object".

    As for the rationale behind the choice, it might have something to do with “Prototypal inherience” the language has. https://tc39.es/ecma262/multipage/overview.html#sec-objects

    Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain.

    We can understand this to mean that prototype chains are null terminated ;)

    For example:

    > Object.getPrototypeOf({}) === Object.prototype
    true
    > Object.getPrototypeOf(Object.getPrototypeOf({}))
    null
    > Object.getPrototypeOf(null)        TypeError: not an object
    

    Uhh…

    Now, let’s go to some abstract algebra. All good (closed) binary operations we deal with have an identity or neutral value. For example: addition has 0, multiplication has 1, boolean and has true, boolean or or xor has false. Performing these operations with the neutral value does not change the other operand: for example, x + 0 == x, a * 1 == a, true && b == b and so on. If you admit min and max as operators, you can see why ∞ and -∞ are the neutral values, respectively: min(∞, x) == x and max(-∞, y) == y for every (real) value of x and y. Observe how Array.prototype.reduce works (with its second argument) for inspiration on why and how all this matters: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

    For mathematicians: closed, because the operators are maps S × S →S, to exclude <, > etc. as they map to Bool. Oh, they are relations, bla bla … real numbers, we don’t want to deal with other total orders here, there should be some way to call orders that have both top and bottom values, complex numbers don’t have orders (usual ones, are there unusual ones?), bla bla bla

    As for the last one, sigh… https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal

    Oh, that !s in there aren’t boolean not… they are… (looks it up) argh, read it yourself https://tc39.es/ecma262/multipage/notational-conventions.html#sec-returnifabrupt-shorthands

    • ûnkreativiteit@c.im
      link
      fedilink
      arrow-up
      1
      ·
      20 hours ago

      Me, wasting my time explaining an ECMAScript meme… I be like, I need to somehow justify the time spent learning about all of these… it was the language I started my programming journey with… sigh

  • jaark@infosec.pub
    link
    fedilink
    English
    arrow-up
    82
    ·
    14 days ago

    I’m no expert and I know that javascript is full of wtf moments, but please… Let it be B

    It’s not gong to be B, it’s it.

    • ImplyingImplications@lemmy.ca
      link
      fedilink
      arrow-up
      98
      arrow-down
      1
      ·
      13 days ago

      It is true. Math.min() returns positive Infinity when called with no arguments and Math.max() returns Negative Infinity when called with no arguments. Positive Infinity > Negative Infinity.

      Math.min() works something like this

      def min(numbers):
        r = Infinity
        for n in numbers:
          if n < r:
            r = n
        return r
      

      I’m guessing there’s a reason they wanted min() to be able to be called without any arguments but I’m sure it isn’t a good one.

      • bss03@infosec.pub
        link
        fedilink
        English
        arrow-up
        39
        arrow-down
        4
        ·
        13 days ago

        So, the language isn’t compiled (or wasn’t originally) so they couldn’t make min() be an error that only a developer saw, it has to be something that the runtime on the end-user system dealt with. So, it had to be assigned some value. Under those restrictions, it is the most mathematically sound value. It makes miniumum-exactly-2(x, min(<…>)) be exactly the same as min(x, <…>), even when the “<…>” has no values.

        As a developer, I see a lot of value in static analysis, including refusing to generate output for sufficiently erroneous results of static analysis, so I don’t like using JS, and the language that I tinker with will definitely have a separate compilation step and reject the equivalent of min(). But, if I HAD to assign something like that a value, it probably would be a representation of infinity, if we had one (probably will due to IEEE floats).

        HTH

        • hades@lemm.ee
          link
          fedilink
          arrow-up
          10
          arrow-down
          1
          ·
          13 days ago

          The language not being compiled has nothing to do with error handling. You could have a min function that operates on dynamic arrays (e.g. std::min_element in C++ or min() in Python).

          • bss03@infosec.pub
            link
            fedilink
            English
            arrow-up
            4
            ·
            13 days ago

            Not having a separate compilation step absolutely affects error handling. With a compilation step, you can have errors that will only be seen by and must be address by a developer prior to run time. Without one, the run time system, must assign some semantics to the source code, no matter how erroneous it is.

            No matter what advisory “signature” you imagine for a function, JS has to assign some run time semantics to that function being called incorrectly. Compiled languages do not have to provide a run time semantics to for signatures that can be statically checked.

            • BatmanAoD@programming.dev
              link
              fedilink
              arrow-up
              3
              arrow-down
              2
              ·
              12 days ago

              Without one, the run time system, must assign some semantics to the source code, no matter how erroneous it is.

              That’s just not true; as the comment above points out, Python also has no separate compilation step and yet it did not adopt this philosophy. Interpeted languages were common before JavaScript; in fact, most LISP variants are interpreted, and LISP is older than C.

              Moreover, even JavaScript does sometimes throw errors, because sometimes code is simply not valid syntactically, or has no valid semantics even in a language as permissive as JavaScript.

              So Eich et al. absolutely could have made more things invalid, despite the risk that end-users would see the resulting error.

              • bss03@infosec.pub
                link
                fedilink
                English
                arrow-up
                3
                arrow-down
                2
                ·
                12 days ago

                Python also has no separate compilation step and yet it did not adopt this philosophy

                Yes. It did. It didn’t assign exactly the same semantics, but it DOES assign a run time semantic to min().

                • BatmanAoD@programming.dev
                  link
                  fedilink
                  arrow-up
                  3
                  ·
                  edit-2
                  12 days ago

                  I’m addressing the bit that I quoted, saying that an interpreted language “must” have valid semantics for all code. I’m not specifically addressing whether or not JavaScript is right in this particular case of min().

                  …but also, what are you talking about? Python throws a type error if you call min() with no argument.

            • hades@lemm.ee
              link
              fedilink
              arrow-up
              1
              arrow-down
              1
              ·
              12 days ago

              I agree, compiled languages prevent large classes of errors, including invoking functions with wrong parameters. However, whether or not you define calling max() with no arguments to be an error or not is unrelated to your language being compiled or interpreted. You could define max() to be -inf in C++ if you wanted, even though the language allows you to prevent invocations of max() with no arguments altogether.

              • bss03@infosec.pub
                link
                fedilink
                English
                arrow-up
                1
                ·
                12 days ago

                The run time still has to assign a semantics to it, even if that semantics is a fatal error. In a compiled language, you can prevent the run time from having to assign any semantics by eliminating the error condition at compile time.

      • timhh@programming.dev
        link
        fedilink
        arrow-up
        4
        ·
        12 days ago

        I’m guessing there’s a reason they wanted min() to be able to be called without any arguments but I’m sure it isn’t a good one.

        It not a totally unreasonable definition. For example it preserves nice properties like min(a.concat(b)) == min([min(a), min(b)]).

        Obviously the correct thing to do is to return an optional type, like Rust does. But … yeah I mean considering the other footguns in Javascript (e.g. the insane implicit type coersion) I’d say they didn’t do too badly here.

      • wise_pancake@lemmy.ca
        link
        fedilink
        arrow-up
        13
        ·
        edit-2
        13 days ago

        Math.min.length is 2, which weakly signals that it’s designed to handle at least two parameters

        Why would they even define this value?

        Note: I’m not a js dev, do most functions have length?

          • Venator@lemmy.nz
            link
            fedilink
            arrow-up
            7
            ·
            13 days ago

            Most people don’t use JS because they think it’s perfect… they use it because it’s the language that works on web browsers… or because thier coworkers made something in it… or because the library that does what they want uses it…

        • bss03@infosec.pub
          link
          fedilink
          English
          arrow-up
          1
          ·
          edit-2
          13 days ago

          All functions built with function name(args) { body } syntax have a length based on the form of args. Other ways to create functions might set length (I’m not sure). Most of the functions provided by the runtime environment do have a length, usually based on the number of “required” arguments.

      • kryptonianCodeMonkey@lemmy.world
        link
        fedilink
        arrow-up
        2
        ·
        12 days ago

        Its the min value of the input params, or Infinity.

        And the reason it’s Infinity If there is no input, for better or worse, under the hood the method is assigning a variable, min, the highest value possible and then comparing it to each element in the list, reassigning it when it encounters an element lower than its value at the time. So it will obviously always be reassigned if there are any elements at all (if they’re less than Infinity, I guess). But if there are no elements, it’s never reassigned, and thus returns Infinity. It could have just signed min to the first element instead if Infinity, but that would lead to a runtime error when min was run without a function. If you’re not going to throw a runtime error though, it makes sense for min to return Infinity because, what other number could you return that couldn’t actually be the minimum

    • sp3ctr4l@lemmy.dbzer0.com
      link
      fedilink
      English
      arrow-up
      14
      arrow-down
      5
      ·
      edit-2
      13 days ago

      I also am not familiar with javascript anymore…precisely because of this, exact, insane bullshit.

      B… and/or C… evaluating as FALSE are the only things that… should even kind of make sense, according to my brain.

      Though at this point in my life, I have unironically had a good number of concussions and contusions, so … well you’d think that would help with JS development.

      Javascript is insanity, and I am still convinced it is at least 40% responsible for Notch losing his goddamned mind.

      ‘null’ is somehow an object. because fuck you, thats why!

      Is… 0 == ‘’ … is that two single quotes ’ ’ ?

      Or one double quote " ?

      If… it is one double quote… that wouldn’t even evaluate, as it would just be an empty string without a defined end…

      But if it was two single quotes… that would just be a proper empty string… and because of forced type coercion, both 0 and ‘’ are FALSE when compared with ==, but not when compared with ===, because that ignores forced type coercion…

      https://www.w3docs.com/snippets/javascript/when-to-use-double-or-single-quotes-in-javascript.html

      Oh my fucking god WHY?!

      Just fucking use one special character to delimit strings!

      Don’t have two that don’t work together and also behave differently even when you pick just one of them… GraaaghhH!

      brb, figuring out where Larry Ellison lives…

      • jaark@infosec.pub
        link
        fedilink
        English
        arrow-up
        5
        arrow-down
        1
        ·
        edit-2
        13 days ago

        I don’t think my sanity can take all of these explanations.

        Though I just spotted one that’s worse than null being an object …

        typeof NaN
        "number"
        

        I mean, come on… it’s even in the fucking name!

        Edit - fixed capitalisation in ‘NaN’

      • traches@sh.itjust.works
        link
        fedilink
        English
        arrow-up
        2
        ·
        13 days ago

        It’s pretty easy to avoid all of these, mostly by using ===. Null being an object is annoying and is one of the reasons ‘typeof’ is useless, but there are other ways to accomplish the same thing.

        JavaScript has a lot of foot guns, but it’s also used by literally everyone so there is a lot of tooling and practice to help you avoid them.

    • skisnow@lemmy.ca
      link
      fedilink
      English
      arrow-up
      24
      ·
      13 days ago

      That one wasn’t the one I had issues with, since the concept is essentially the same across all languages. We say it’s false because we can’t conclusively say that it’s true. Same as the reason why null != null in SQL.

      • Victor@lemmy.world
        link
        fedilink
        arrow-up
        5
        ·
        13 days ago

        It also makes a lot of conditional expressions less complicated because comparisons of all kind against NaN return false.

  • mmddmm@lemm.ee
    link
    fedilink
    arrow-up
    30
    arrow-down
    1
    ·
    13 days ago

    The one option that is mandated by an ISO standard.

    Besides, if max and min are going to have a value without any parameter, it has to be exactly those Javascript uses. Unless you have a type that define other bounds for your numbers. And null always have a pointer type (that is object in Javascript), for the same reason that NaN always have a number type.

    The only one that is bad on that list is D.

    • Valmond@lemmy.world
      link
      fedilink
      arrow-up
      9
      arrow-down
      1
      ·
      13 days ago

      I’d say C too because that’s the only one that would be True in a normal programming language and this is javascript so…

      • povario@discuss.tchncs.de
        link
        fedilink
        English
        arrow-up
        4
        ·
        13 days ago

        probably not true in most other langauges. although I’m not well versed in the way numbers are represented in code and what makes a number “NaN”, something tells me the technical implications of that would be quite bad in a production environment.

        the definitive way to check for NaN in JS would probably be something like

        // with `num` being an unknown value
        
        // Convert value to a number
        const res = Number(num);
        
        /*
         * First check if the number is 0, since 0 is a falsy
         * value in JS, and if it isn't, `NaN` is the only other
         * falsy number value
         */
        const isNaN = res !== 0 && !res;
        
      • Remavas@programming.dev
        link
        fedilink
        arrow-up
        5
        arrow-down
        1
        ·
        13 days ago

        It’s not true in a normal programming language. If it is true in yours, you should stop using it immediately.

        • Valmond@lemmy.world
          link
          fedilink
          arrow-up
          1
          ·
          13 days ago

          A non type should be a type. It should be of the type none. And it is in good script languages like Python so I don’t know why you think it shouldn’t.

              • Remavas@programming.dev
                link
                fedilink
                arrow-up
                1
                ·
                edit-2
                8 days ago

                That’s not a type. A NaN is a floating point number (of type float). I used numpy because that’s the easiest way to get a NaN.

                This is part of the floating point standard.

                This was never about None, which is a completely different thing.