Sunday, August 28, 2016

The double-tilde (~~x) technique in JavaScript - What it is, and why you should be careful about using it.


What is it?

The ~ (tilde) operator in JavaScript is the often-overlooked bit-wise not. For integers, it is the equivalent to running:

~x == -(x + 1)

So ~(10) will give you -11. There's another caveat to the ~ operator. It casts floating point numbers to integers by dropping everything after the decimal. So in the more general sense,

~x == -(Math.trunc(x) + 1)

Recall that Math.trunc() is kind of like Math.floor(), except the value (positive or negative) will always be rounded towards 0. The ~~ technique is a common trick you'll find a lot of developers using. Let's resolve it:

~~x = -(Math.trunc(-(Math.trunc(x) + 1)) + 1)
-(Math.trunc(-(Math.trunc(x)) - 1) + 1)
-(Math.trunc(-(Math.trunc(x))) + 1 - 1)
= --Math.trunc(x)

Essentially, ~~ is used as a short-hand hack for Math.trunc(). 

But you should probably never use it.

I'm pretty lazy so I use to use this a lot... until it got me in trouble. It turns out that ~~ doesn't work for really large numbers. For instance, when I run ~~1000000000000, the result is -727279968, so in this case not only did we lose a ton of precision, the answer actually has the wrong sign! So if you were expecting a positive number because the input was positive, this type of thing can really wreak havoc, like crashing your Node.js server or whatever.

But even if you understand the way that numbers work in JavaScript and only use the ~~ trick where appropriate, I would still contend that using this technique is detrimental in the same way as goto statements or the xor swap algorithm. It's esoteric, and prone to bugs. It is not beginner-friendly, doesn't come with documentation, and if accepted by convention could lead unknowing developers down the path to buggy code.


Instead of using ~~ just stick with Math.floor(). If you want a way to truncate decimals (flooring both positive and negative numbers towards 0), add this declaration at the top of your code:

    Math.trunc = function(value){
        return Math.sign(value) * Math.floor(Math.abs(value));

Note that Math.trunc() is already available in ECMAScript 6 compliant JavaScript engines (which is used by most modern browsers, but not all), and doesn't need to be added in those environments.

Tuesday, August 9, 2016

Add sleeps or yields to JavaScript loops with Sequencr.js

Add sleeps or yields to JavaScript loops with Sequencr.js

Ever wish JavaScript had a built-in sleep function to help you build loops for computationally difficult tasks without killing the browser? Yea, we all have. Obviously we can always cascade setTimeouts, but can get messy fairly quickly.

Recently, I published a JavaScript library, Sequencr.js, that's helped me with this problem. It's fairly simple, but so deceptively useful that I've found myself using it in tons of different projects. Check out the project page:



Sequencr.js is now  a fully functional promise library. It makes promises a lot easier to work with and adds some interesting design patterns like asynchronous promise-based iterators.