← Back to context

Comment by EdiX

11 years ago

    Small modules are easy to reason about

They really aren't, when I'm reading is-positive-integer(x) and wonder if 0 is positive I need to hunt down the definition of positive through two packages and as many files. And it gets wrose if both your code and one of your dependencies required 'is-positive-integer' and I have to also figure out which version each part of the code base is using.

If you had written (x > 0) I would have known immediately, it also wouldn't be doing the same thing as is-positive-integer(x) but how many calls to is-positive-integer are actually correct in all the corner cases that is-positive-integer covers?

And then there's the other problem with dependencies: you are trusting some unknown internet person to not push a minor version that breaks your build because you and Dr. is-positive-integer had different definitions of 'backwards compatibility'.

JS does not have an Integer type, so (x > 0) does not work. Now if you add all those checks necessary to see whether you're actually dealing with an integer here, you get to a point where you cannot be sure anymore whether there aren't any weird type coercion issues there and need to start writing tests. Suddenly your whole positive integer check took 1h to write and you still cannot be sure whether there's something you didn't think of. I'd rather use an external library for that that's properly unit tested.

  • A module doesn’t solve that kind of type confusion, though. Static typing does. The next best thing in JavaScript is passing consistent types of values to your functions, so just write

      function isPositiveInteger(x) {
          return x > 0 && Number.isInteger(x);
      }
    

    and always pass it a number. (Of course, this shouldn’t even be a function, because JavaScript is confused about the definition of “integer” – maybe you really want `x >>> 0 === x` – and apparently is-positive-integer is confused about the definition of “positive”, so it’ll be clearer to just put things inline.)

    • > A module doesn’t solve that kind of type confusion, though. Static typing does.

      That's the root of all the problems, though, isn't it? JavaScript is just a terrible language.

      Actually, that's not really fair. It's a great little language for writing late-90s Dynamic HTML, maybe just a little too powerful. And that additional power enables people to build cathedrals of cruft in order to Get Things Done.

      I don't like Scheme (Lisp is IMHO better for real-world, non-academic work), but I still wonder how much things would have been if Eich had been allowed (or had chosen) to implement a small Scheme instead of JavaScript. The world of web software engineering would be so profoundly better.

      Maybe WebAssembly will save us all.

      4 replies →

    • I would swap the expressions on each side of the '&&' around. While JS doesn't care (as it'll apply '>' to just about anything, even in strict mode), this is perhaps a stronger statement of intent:

          return Number.isInteger(x) && x > 0;
      

      Thus the more general assertion (is it an integer) guards the more specific specific one (is it greater than zero).

      1 reply →

    • x >>> 0 changes a negative integer to an unsigned (positive) 32-bit integer. You can have integers greater than 32 bits. They're represented internally as floats. Bitwise operators make 32-bit assumptions, with the top bit as a sign bit, unless you do x >>> 0, in which case you can revert a sign bit overflow back to a positive integer. If you have a positive integer that's greater than 32 bits, x >>> 0 === x fails. The expression (84294967295 >>> 0 === 84294967295) is false.

      Don't even get me started on negative zero.

      1 reply →

    • The module checks that the positive integer is less than Number.MAX_SAFE_INTEGER constant, while yours would lead to unsafe comparisons if we trust its validity as a number.

      1 reply →

  •     JS does not have an Integer type, so (x > 0) does not work
    

    It depends on what the surrounding code actually does wheter (x > 0) works or not. Depending on the version of is-positive-integer you are using a positive instance of the class Number may return true, false or cause an error.

    PS. never mind that the implementation of is-positive-integer is extremely inefficient.