Re:Blessed Are the JavaScript Developers
by danShumway on Thursday September 03, 2020 @09:54AM
(#24364058)
If you don't do eager casting, you get inconsistent sorting behavior depending on the algorithm and unsorted list order.
Under the current algorithm,
randomize_array(['3', 5, 10, '11']).sort()
will always give you [10, '11', '3', 5]
Under your proposal, where our casts are dependent on what two elements we're currently comparing, you might get [10, '11', '3', 5]
or ['3', 5, 10, '11']
Try it yourself: ['11', 10, '3', 5].sort((a, b) => a < b ? -1 : 1);
[10, 5, '3', '11'].sort((a, b) => a < b ? -1 : 1);
The only way that type-specific sorting algorithms work is if we check the entire array before we start sorting, which has performance implications. It can't be on-the-fly, we either have to commit to type-checking the entire array, or commit to casting the entire array. I think casting is more consistent, I don't like the idea of an algorithm changing underneath me because of a type error. But in either case we can't change our sorting behavior mid-sort.This is part of the reason why recommendations on how to sort an array of integers is to use a sort method like
(a, b) => a - b
instead of the comparison operator -- because most of the time subtraction will cast everything to a number across the entire array, including the strings. For most people, this will be fine. To head off what would logically be the next thing to suggest, we also can't rely on `a - b` for a default sorting algorithm for `sort2`, because of ['11', 10, '3', 5, {}].sort((a, b) => a - b);
[{}, 10, 5, '3', '11'].sort((a, b) => a - b);
You can still do the cast if needed when they're different types (once the < operator is applied). Whatever, that's the norm for JavaScript. But in this case, the cast to a string happens before it even knows it needs to, which is what makes the OP's case so egregious. In this case all the values are the same type - numbers - and they still get needlessly cast to strings. IMO, waiting until the < to do any casting is not only more reasonable overall, but is actually more inline with expected JS behaviors.