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.
There are already some quite advanced compilers that treat JavaScript itself as just a web assembly language, you don't technically have to wait for WebAssembly. TypeScript (some type safety) PureScript (Lots of type safety) and GHCJS (MOUNTAINS of type power) all work right now, though the latter is still experimental grade.
But I don't think an initial choice of implementing a Scheme would have helped. The idea of +0 vs 0 vs -0 could just have easily happened in a Scheme, same too for the reliance on stringy types. Those are symptoms of a rushed design and an unwillingness to accept the temporary sharper pain of invalidating existing bad code to produce a new better standard (the exact same tendency - to dig in deeper rather than risk the pain of turning back - is literally how spies managed to convince people to commit treason).
Then of course there's also the great risk that, just like Scheme not-in-the-browser, Scheme-in-the-browser might never have widely caught on.
> There are already some quite advanced compilers that treat JavaScript itself as just a web assembly language, you don't technically have to wait for WebAssembly.
Yeah, there's even a Common Lisp which compiles to JavaScript …
> The idea of +0 vs 0 vs -0 could just have easily happened in a Scheme, same too for the reliance on stringy types.
I don't necessarily know about these specific examples: the Scheme standards have been quite clear about their numeric tower and equality standards.
I think your general point about the hackiness which was the web in the 90s, and the unwillingness to break stuff by fixing things holds, though. And of course it wasn't just the web: I recall that the Makefile syntax was realised to be a mistake weeks into its lifetime, but they didn't want to fix it for fear of inconveniencing a dozen users (details fuzzy).
> Then of course there's also the great risk that, just like Scheme not-in-the-browser, Scheme-in-the-browser might never have widely caught on.
I dunno — would a prototypal language have ever caught on were it not for the fact that JavaScript is deployed everywhere? I can imagine a world where everyone just used it, because it was what there was to use.
And honestly, as much as I dislike Scheme, it would have fit in _really_ well with JavaScript's original use case and feel. And if the world had had a chance to get used to a sane, homomorphic programming language then maybe it might have graduated to a mature, industrial-grade, sane, homomorphic language.
It's easy to say things like this. It's a lot harder to actually suck it up and live with what happened. Try to make progress, remember that's what all of the offenders in this story are trying to do. Whether or not it is perceived like that by the community.
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).
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.
I thought all numbers in Javascript were represented as 64-bit floats. Therefore you can do correct integer math up to 53 bits without getting into too much weirdness (bigger than that and the weirdness is guaranteed).
I didn't know the >>> operator converts to 32-bit. How does it do that? Mask off the top bits? Or give you a NaN if it's bigger?
But (and someone please correct me if I'm wrong), at the end of the line it's still represented as a 64-bit float internally and accurately.
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.
The name of the function, though, isn’t `isPositiveSafeInteger`; it matches `Number.isInteger` instead.
Or maybe you don’t just want safe integers, maybe you want `x >>> 0 === x`, or `x > 0 && (x | 0) === x`, or…. This is what I meant about JavaScript being confused about the definition of “integer”.
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.