My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Tuesday, July 28, 2009

Some Fun From NekoVM Specs

Few minutes ago I've read about last haxe miracle: translation from an AS2 like ECMAScript 4th programming language, haxe itself, into C++ rather than "just" JavaScript, PHP, and ActionScript 2 or 3, or Neko.

NekoVM is a project I already knew before but since not a single host I know supports it, I have never investigated too much about its features but apparently NekoVM is a damn fast Virtual Machine for Neko code which is basically JavaScript with few differences/limitations. It is still a prototypal based programming language, and we all love it, isn't it, plus some better rule about static types, bytes management, closures, goto statement with portable scope, operator overload for objects, ability to compile C files into ndll, Apache module, MySQL, Zlib, on and on ... truly interesting!

Reading quickly the entire language specs, I tried to figure out if it is possible to reproduce Neko via JavaScript in order to use one language for both server and client: Jaxer style (I do not link Jaxer 'cause AFAIK it seems to be a failed project).

Well, I think without a sandbox it is possible to reproduce 70% of language specs. Via sandbox probably 85%, but 100% is quite utopia due to operator overload not that easy to manage via JavaScript and valueOf in a cross browser way (with firefox it is more simple thanks to "number" string as first argument if the operation is a plus so __add rather than __radd could be partially possible ... never mind).

$apply and $closure from NekoVM


These two functions are both simple and useful in our daily JS tasks. $closure is usually known as delegate or bind, while $apply is some fun we could have in a flexible language as JavaScript is.

function $apply(fn){
// WebReflection from NekoVM
var length = fn.length,
args = []
;
return (function $apply(){
args.push.apply(args, arguments);
return length <= args.length ? fn.apply(this, args) : $apply;
}).apply(this, args.slice.call(arguments, 1));
};

Test case from the source?

var f = function(x,y) { return x + y };

alert(
f(1,2) === $apply(f,1)(2) &&
f(1,2) === $apply(f,1,2) &&
f(1,2) === $apply(f)(1)(2)
); // true

I like the multi bracket style and thanks to its nature it is possible to split a function up to some parameter and inkect different scopes:

var f = function(b, c) {
return this.a + b + c;
};

var o1 = {a:1},
o2 = {a:2},
k = 2, // constant ...
sum = $apply(f)
;

o1.sum = sum(k);
o2.sum = o1.sum.call(o2); // injected
// o2.sum = sum(k); // equivalent


alert(o1.sum(3)); // 1 + 2 + 3 == 6
alert(o2.sum(3)); // 2 + 2 + 3 == 7

I am not sure if "this" should be that malleable, probably a version with static "this" during first call could be better?

function $apply(fn){
// WebReflection V2 from NekoVM
var length = fn.length,
args = [],
self = this === window ? null : this
;
return (function $apply(){
args.push.apply(args, arguments);
return length <= args.length ? fn.apply(self || this, args) : $apply;
}).apply(self, args.slice.call(arguments, 1));
};

In above case if we call $apply() the scope will be malleable, otherwise it will be fixed $apply.call(o2, a).

The other one is less problematic, since it is a common bind.

var $closure = (function(){
// WebReflection from NekoVM
var slice = Array.prototype.slice;
return function $closure(fn, self){
var args = slice.call(arguments, 2);
return function $closure(){
return fn.apply(self, args.concat(slice.call(arguments, 0)));
};
};
})();

The idea is to be able to trap directly the scope in order to make it safe whenever and however it is executed.

var add = function(x,y) { return x + y };
var plus5 = $closure(add, null, 5);
alert(
plus5(2)
); // 7

var add = function(y){return this.x + y};
var plus5 = $closure(add, {x:5});
alert(
plus5(2)
); // 7

Easy? Let's see what else I could create from NekoVM specs 8-)

3 comments:

zproxy said...

Have you tried jsc compiler with ScriptCoreLib too?
:)

Shabunc said...

does the $closure func act actually like Function.prototype.bind method described in ECMAScript 5th edition?

Andrea Giammarchi said...

zproxy, nice project but:
Want build better web sites, but javascript is too hard?
JavaScript is my breakfast in the morning so I guess I'll never use it :D

jokes a part, haxe is ECMAScript, as C# is, I cannot understand why people do not get it properly.

Shabunc, that bind is really similar. ECMAScript 5 got it from Prototype library if I am not wrong.