Introducing BackTick, a.k.a. StanScript ; ) a Clojure/Scala/Lisp/Python-inspired JavaScript superset

Why `backtick`? Because (almost) all of the syntax extensions were introduced using only one character. Yep, you got it – the backtick ; )

Supported features:
– Python-like operator overloading (by defining __iadd__, __eq__, etc. methods in the object or prototype), e.g.: x.__iadd__ = function(y) { this.data += y; }; x `+= 1;
– Subscript operators are also overloadable, e.g. x`[0] = 1; x`.y = 1; etc.
– Ternary operator (?:) is also overloadable, e.g. x `? 1 : 0; translates to x.__ternary__(1, 0)
– Concise lambda function declaration, e.g.: `(a, b, c) { return a + b + c; } or with default-return even: `(a, b, c) { a + b + c; }
– The last statement in a function is by default its return value, e.g.: function(a, b, c) { if (a > b) a – b; else c; }
– Short variable declaration, e.g.: `x = 1; instead of var x = 1;
– Short new operator call, e.g.: `Vector3(1, 2, 3) instead of new Vector3(1, 2, 3)
– Short access to “this” operator, e.g. `.x = 1; instead of this.x = 1 for “this” members, and “ for literally “this”, e.g. “ `+= 1 translates to this.__add__(1)
– Chaining operator ->, e.g. x() -> y(1, 2) -> z(‘test’) is equivalent to z(‘test’, y(1, 2, x()))

As you can see, backtick is everywhere ; )

Now, by combining the above functions and writing some helpers, we can write some really concise programs:

switch_(a, [‘0’, `(){ x+=1; }, ‘1’, `(){ y += 1 }]);

map(`(x){ x * x; }, A) -> filter(`(x){ x % 2 == 0; }) -> map(`(x){ console.log(x); });

`v = `Vector3();
v `+= `Vector3(1, 2, 3) `+ `Vector(4, 5, 6);

if (v `!= 0) { console.log(‘Non-zero vector.’); }

If we define __index__ to return a little proxy object:

MyClass = `() { `.data = []; }
`_ = MyClass.prototype;
_.__index__ = `(n) { that = this; { ‘valueOf’: `() { that.data[n]; }, __assign__: `(val) { that.data[n] = val; } }}
}

we can also do stuff like this:

`x = `MyClass();
x`[5] = 10;

and it will use the proxy __assign__ method to do custom subscript assignment to MyClass.

I’m sure examples could be multiplied. This thing took my whole evening and it’s based on UglifyJS Javascript parser. The following bugs are known at the moment (possibly more to come):

– Dictionaries are mistaken for blocks with labeled statements if the first key is identifier and not string or number, e.g. {valueOf: function() { }, ‘toString’: function() { }} will result in an error, whereas: {‘valueOf’: function() { }, toString: function() { }} will work correctly. This is UglifyJS’s fault, I didn’t have time to fix it yet. Actually in UglifyJS it didn’t work even if the first key was string, that’s already my workaround ; )

Anyhow, enjoy ; )

You can play with the new language here: http://algoholic.eu/workspace/backtick/play.html

Leave a Reply

Your email address will not be published. Required fields are marked *