• Konlanx@feddit.de
    link
    fedilink
    arrow-up
    59
    arrow-down
    3
    ·
    1 year ago

    This is due to the default sorter in JavaScript sorting by the string value. The reason for that is that this won’t create errors at runtime. Since JavaScript does not have types, this is the safest way of sorting.

    This works:

    const unsorted = [1, 100000, 21, 30, 4]
    const sorted = unsorted.sort((a, b) => a - b) 
    
    • jmcs@discuss.tchncs.de
      link
      fedilink
      arrow-up
      68
      arrow-down
      2
      ·
      1 year ago

      Which is a fine decision if you have a programming language to do silly stuff on a personal geocities page, but a horrible one when you start using that language to handle serious data. Silently ignoring what’s probably a bug is dangerous.

      • seitanic@lemmy.sdf.org
        link
        fedilink
        arrow-up
        25
        ·
        1 year ago

        Which is a fine decision if you have a programming language to do silly stuff on a personal geocities page

        And that is, of course, what it was designed for.

        JS is brilliant considering that it was created by one dude in 10 days. Nobody thought it would become nearly as important as it has become.

        • luciferofastora
          link
          fedilink
          arrow-up
          1
          ·
          1 year ago

          Nobody thought it would become nearly as important as it has become.

          This is why I’m wary about all the quick and easy “temporary” solutions I’m building because I don’t have the time to do it properly, and pushing hard to replace them with a more solid permanent one at any chance. I’m already mortified at the idea of someone proficient ever looking at any of it in the inevitable event of it becoming a long-term fixture.

    • AVincentInSpace@pawb.social
      link
      fedilink
      English
      arrow-up
      1
      ·
      edit-2
      1 year ago

      ah yes, a reasonable solution to that problem that any human would think of

      ah yes, a reasonable problem that any human would think of – “what if someone tries to sort a list containing some integers and some arrays, and our interpreter needs to keep chugging instead of telling the programmer they fucked up?”

      • luciferofastora
        link
        fedilink
        arrow-up
        1
        ·
        1 year ago

        For those unfamiliar with the magic behind this, the rough outline goes like this:

        ++ is an operator to increment a number.
        The string 'a' can’t be incremented, because it’s not a number.
        ++'a' thus evaluates to NaN (Not a Number), which in turn is converted to the string 'NaN'.

        The string concatenation expression is thus equivalent to 'b' + 'a' + 'NaN' + 'a' which evaluates to 'baNaNa' and is then lowercased to 'banana'.

        (You could get more pedantic about the exact evaluation mechanisms and order, but if you’re proficient enough to make sense of that, you probably didn’t need the explanation in the first place)

    • StarkillerX42@lemmy.ml
      link
      fedilink
      arrow-up
      3
      ·
      edit-2
      1 year ago

      “Actually, this one isn’t ‘Wat’, it’s part of what makes Ruby awesome and powerful, unless of course you actually do this, at which point it’s ‘Wat’”

      • Zeragamba@lemmy.ca
        link
        fedilink
        arrow-up
        3
        ·
        edit-2
        1 year ago

        let’s talk about Ruby

        Ruby like most programming languages doesn’t support bare words, [undefined variable exception]

        but if you define a particular method_missing, suddenly Ruby supports bare words. [ruby repeating what was typed]

        Now this isn’t deserving of wat. this actually shows just how awesome Ruby is. [Drummer_t-rex.jpg]

        But if you actually do this then…

        Wat

      • affiliate@lemmy.world
        link
        fedilink
        arrow-up
        7
        ·
        1 year ago

        is there a good reason for javascript to work like that? python also isn’t typed like C and it sorts integer lists in the “normal” way, so it seems avoidable. (i don’t really know what im talking about here. i’ve never used javascript and i’m not familiar with how typing works under the hood.)

        • Quasari@programming.dev
          link
          fedilink
          English
          arrow-up
          20
          arrow-down
          2
          ·
          1 year ago

          Mainly because JavaScript was designed to work along side HTTP in a browser. Most of its input will be text, so defaulting common behavior to strings makes some sense.

          • severien@lemmy.world
            link
            fedilink
            arrow-up
            5
            ·
            edit-2
            1 year ago

            That’s misleading at best and most likely just false, and it’s worrying it’s so upvoted.

            There’s no historical record explaining why this was designed this way, but we can infer some things. HTTP is very unlikely a factor, XHR / AJAX has been added years after the .sort() function. Additionally, it doesn’t make sense in the context that other comparisons are not string-wise (sort()/quicksort is basically a series of comparisons).

            The trouble with JS arrays is that they can contain any values - e.g. [false, undefined, 1567, 10, "Hello world", { x: 1 }]. How do you sort those? There must be one function to compare every combination of value, but how do you compare booleans and objects?

            There’s no such function which would provide reasonable results. In that context, doing .toString() and then string-wise comparison/sorting doesn’t seem that crazy - every object has .toString(), it will compute something, and often it will work well enough.

            There could be some additional smartness - if the array contains numbers only, it could choose to use a number-wise comparison function. But that would require a) extra implementation complexity (JS was famously designed in short time) and b) reduced performance - since JS runtime doesn’t know what type of values are present in the array, it would have to scan the whole array before starting the sort. But I guess the a) was the decisive factor in the beginning and backwards compatibility prevented improving the function later.

            • Quasari@programming.dev
              link
              fedilink
              English
              arrow-up
              3
              ·
              edit-2
              1 year ago

              You are probably correct. I don’t know if it’s true, it’s probably more likely it was a way for it not to fail.

              I said HTTP mainly because HTML is plaintext because of it. 1.0s main purpose was to manipulate the page. Of course Array objects weren’t added til 1.1, when netscape navigator 3.0 released, but it was still mostly 1.0 code. I felt like having everything be coercable to string made it easy for you to just assign it to the document. If you assigned the wrong thing it wouldn’t crash.

              I originally thought there was a precursor to microsofts XMLHTTP in an earlier version due to the 1997 ECMAScript documentation specifically talking about using it both client and serverside to distribute computations, but it was far more static. So, I’m probably just wrong.

        • kevincox@lemmy.ml
          link
          fedilink
          arrow-up
          13
          arrow-down
          1
          ·
          edit-2
          1 year ago

          The hard part is sorting values of different types.

          Python 2 had a order of built it types. Something like None < bool < numbers < strings. This means that you could sort anything like JavaScript and behaves fairly reasonably.

          Python 3 takes the “safer” approach and comparisons of different types throw an exception. (You can override the comparison behavior for your own types and do something different).

          JavaScript has conventionally been a very loosely typed language. So it almost certainly wouldn’t have chosen the exception throwing option. It does something similar to Python 2. But instead of just directly comparing the values of different types it converts them to strings first, then compares everything as a string. This is probably the most reasonable option. Otherwise you would have problems because 10 &lt; "2" and "2" &lt; 3 but 3 &lt; 10. How can that work? You have no total ordering! So basically because the comparison operators convert to strings if either argument is a string the default sort comparator really doesn’t have a choice but to do convert to string. The other option would be to define a total order just for the sort function but that seems more confusing.

      • floofloof@lemmy.ca
        link
        fedilink
        English
        arrow-up
        3
        ·
        edit-2
        1 year ago

        It’s also an incorrect alphabetical sort in many languages that use accented characters. For a correct sort you need to pass it something like the localeCompare function or Intl.Collator.

    • fidodo@lemm.ee
      link
      fedilink
      arrow-up
      19
      arrow-down
      1
      ·
      1 year ago

      You can put any type of value in an array in JavaScript. You can have numbers, strings, booleans, arrays, and objects. So what should the default sort function sort by? Sorting by numbers makes sense, but what if it wanted to sort strings instead?

      When you don’t know what value is in an array ahead of time you can’t assume how to sort it. When you’re controlling the program you can provide a sort function for the type of values you know will be in it, but when you’re writing the standard default sort function, there’s only one type that you can convert all the other types to safely and simply in the most predictable way, which is strings.

    • KiofKi@feddit.de
      link
      fedilink
      arrow-up
      15
      ·
      1 year ago

      "By default, the sort() function sorts values as strings.

      This works well for strings (“Apple” comes before “Banana”).

      However, if numbers are sorted as strings, “25” is bigger than “100”, because “2” is bigger than “1”.

      Because of this, the sort() method will produce incorrect result when sorting numbers."

      https://www.w3schools.com/js/js_array_sort.asp

      • floofloof@lemmy.ca
        link
        fedilink
        English
        arrow-up
        8
        ·
        1 year ago

        It also produces incorrect results in many languages other than English. You can pass it a compare function that uses localeCompare or Intl.Collator to get a correct alphabetical sort.

    • Blackmist@feddit.uk
      link
      fedilink
      English
      arrow-up
      14
      ·
      1 year ago

      Because it turns everything into text first. Just in case you try to sort [1,“apple”,45.99,false,[true,3]] rather than an array of similar things like a normal person.

    • jormaig@programming.dev
      link
      fedilink
      arrow-up
      12
      arrow-down
      3
      ·
      1 year ago

      Because when it’s sorting some of them as ints and some of them as strings. JavaScript has implicit conversion to string.

      • kevincox@lemmy.ml
        link
        fedilink
        arrow-up
        5
        ·
        1 year ago

        Wrong. JavaScript sort’s default comparison function always converts to strings.

        • jormaig@programming.dev
          link
          fedilink
          arrow-up
          4
          arrow-down
          1
          ·
          1 year ago

          Only if one of them is a string right? If you have only numbers then it works fine right? Right? (Please say that I’m right 😭)

          • kevincox@lemmy.ml
            link
            fedilink
            arrow-up
            5
            ·
            edit-2
            1 year ago

            No. It always compares by converting to string. I actually think this is more consistent then having different behaviour if you have a string somewhere in your list.

            Basically the default comparator is a.sort((a, b) => `${a}` &lt; `${b}` ? -1 : 1).

    • Alien Nathan Edward@lemm.ee
      link
      fedilink
      arrow-up
      10
      arrow-down
      1
      ·
      1 year ago

      Think of digits like you would letters. You’re essentially sorting numbers alphabetically. It’s not the right way to do it, of course, but it’s the natural way to do it using a system like computers use that doesn’t necessarily differentiate between digits and letters unless you tell it to specifically.

      • CheezyWeezle@lemm.ee
        link
        fedilink
        arrow-up
        3
        ·
        1 year ago

        I think the main shortcoming here is that there isnt a way to specify the type to sort as, instead you have to write the function to compare them as numbers yourself. If it’s such a simple implementation, why isn’t it officially implemented? Why isn’t there a sortAs() that takes two args, the input list, and a Type value? Check every element matches the type and then sort, otherwise return a Type Error.

        • Alien Nathan Edward@lemm.ee
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          1 year ago

          I mean, there’s a sort() method that takes a comparator(a,b) such that if a comes first it returns 1, if b comes first it returns -1 and if they’re equivalent wrt sortinf it returns 0. If you absolutely need type safe number sorting you can use that to get it.

          • CheezyWeezle@lemm.ee
            link
            fedilink
            arrow-up
            2
            ·
            1 year ago

            Right, but you have to make that comparator yourself, it’s not a built-in part of the language. The only built-in comparator converts values to strings and compares them in code units orders.

            Also, that technically isnt type-safe, is it? If you threw a string or a NaN at that it would fail. As far as I knew, type safe means that a function can handle type errors itself, rather than throwing an exception. So in this case the function would automatically convert types if it was type-safe to prevent an unhandled exception.

            • Alien Nathan Edward@lemm.ee
              link
              fedilink
              arrow-up
              2
              ·
              1 year ago

              Not every use case can be the built-in default. I wouldn’t have made JS weakly typed if I were designing it, but once the decision was made to use weak typing it made sense to either have no default sort method or to have a default sort method that assumes a type.

              What I’ve outlined for you is the interface for a comparator, not the implementation. You can type check and convert and do anything else you want under the hood of the comparator you write.

              • CheezyWeezle@lemm.ee
                link
                fedilink
                arrow-up
                2
                ·
                1 year ago

                It doesn’t have to be the default to be built in, tho. It could be an overloaded function, having the “default” be the typical convert-to-string sorting, and an overloaded function that allows to specify a type.

                It’s just such a common thing, wanting to sort a list by different types, that I’m surprised there hasn’t been an official implementation added like this. I get that it a simple “fix” to make, but I just think that if it’s that simple yet kind of obscure (enough that people are still constantly asking about it) there should be an official implementation, rather than something you have build yourself.

                • Alien Nathan Edward@lemm.ee
                  link
                  fedilink
                  arrow-up
                  2
                  ·
                  1 year ago

                  Thats just JS for you. If you’re being generous, it’s a “quirky” language. If you’re being ungenerous, it’s a steaming pile of arbitrary decisions, gotchas, unexpected behaviors and problems that no one bothered to solve because there’s a workaround.

    • nero@lemmy.world
      link
      fedilink
      arrow-up
      3
      arrow-down
      2
      ·
      1 year ago

      It sorts them based on their unicode character, not the actual numbers. 1 is U+0031, 2 is U+0032, etc.

    • Carlos Solís@communities.azkware.net
      link
      fedilink
      arrow-up
      3
      arrow-down
      1
      ·
      1 year ago

      It’s sad to have the rushed ramblings of a bigot become the fundamental block of the modern world wide web. Why couldn’t it be at least made by a more competent bigot like Carmack?

  • nintendiator@feddit.cl
    link
    fedilink
    English
    arrow-up
    5
    ·
    1 year ago

    Honestly this being javascript I expected the answer to be

    [4, 1, 100000, 30, 21]
    

    (sorted alphabetically by name)

  • Armand1@lemmy.world
    link
    fedilink
    arrow-up
    7
    arrow-down
    4
    ·
    1 year ago

    As annoying as this is, you are meant to use a comparer.

    mapped.sort((a, b) => {
      if (a.value > b.value) {
        return 1;
      }
      if (a.value &lt; b.value) {
        return -1;
      }
      return 0;
    });
    
  • yetAnotherUser@lemmy.ca
    link
    fedilink
    arrow-up
    1
    ·
    1 year ago

    As many people have pointed out already, this happens because JavaScript was rushed. But why do we still use a language whose foundation was built in only ten days(!) for scripting on webpages we build today? Why hasn’t there been a push for web browsers to support other scripting languages (other than maybe Dart)?

    • Kayn@dormi.zone
      link
      fedilink
      English
      arrow-up
      2
      ·
      1 year ago

      There has never been a push because JavaScript works well enough.

      Many of its mistakes have been rectified in later specifications.