Emulating infix operator syntax in javascript

In Maths, we write 1 + 1, but in many programming languages this becomes prefix: +(1, 1) or plus(1, 1) or (plus 1 1) or number(1).plus(1). Many languages directly support an infix notation, e.g. Haskell and Scala. This is particularly nice as a way of unifying the concepts of operators and function while providing a nice syntax for functions with symbolic names like +, -, >>=. I found a way of emulating this in Javascript.

In js, properties of objects can have any name, even if that name is a reserved word or invalid identifier. e.g. {“a” : 3, “><!!”: 3, “private”: 4};. When you refer to a property, you can use either or object["property"]. We’ll exploit the latter.

Example 1: String Split

For a simple example, say I want to split a string by a character.  There’s a function String.prototype.split for this, so I can write:

Let’s change it to a symbolic infix operator. Ideally, we’d like to write:
“a,b,c” | “,”

We can come close:
(“a,b,c”) ["|"] (“,”)

by doing:
String.prototype["|"] = String.prototype.split

So, imagine all values are enclosed in () and all operators enclosed in [""] – we take this on as syntactic noise, but otherwise we have the desired syntax. The key thing is really getting rid of the “.” to make it look more of an operator than “invoking a method on an object”.

Example 2: >>= on Maybe

>>= is the monadic bind operator in Haskell. If you don’t fully understand that sentence, please stop reading and go learn it, it kicks ass and is far more important than this post :)

My favourite monad is Maybe. Here’s a simple example of binding over Maybes in Haskell:

f = \x -> if (x > 3) then Just(x + 1) else Nothing;
g = \y -> y >>= f >>= f

In javascript, it’s tricky to write the monad abstraction, but simple to write specific monads – you just have to repeat yourself a lot. I’ve cooked up a very basic Maybe in Javascript which defines a >>= operator. The equivalent example looks like this:

var f = function(x) {  return x > 3 ? Just(x + 1) : Nothing; };
var g = function(y) {  return (y) [">>="] (f) [">>="] (f); };

The code is up at

Comments are closed.