Allow me to make the case that harmony proxies can ease some of your
(syntactic) pains:
> // 2.) Shorthand for "function", aka the "not lambda"
>
> node.addEventListener("click", #(e){ e.preventDefault(); });
> node.removeEventListener("click" obj!#(e){ ... }); // see #3
>
If what you're looking for is simply a convenient shorthand, Harmony proxies
may partially satisfy your needs.
See: <
http://wiki.ecmascript.org/doku.php?id=harmony:proxies#higher-order_messages
>
Basically, the expression _.foo(x) returns a function(receiver) {
receiver.foo(x) } such that your first example would become:
node.addEventListener("click", _.preventDefault() );
// makes for easy-to-read operations:
> [ ... ].map(#(i){ i+10; });
>
Ah, if only '+' were a message, then you'd be able to write:
[ ... ].map( _.+(10) )
Nevertheless: the pattern array.map(function (e) { e.someMessage() }) should
be common enough such that it can benefit from the '_' shorthand.
> 3.) Syntax for bound function de-reference
>
Using a similar trick as above + MarkM's proposed Ephemeron
Tables<http://wiki.ecmascript.org/doku.php?id=strawman:ephemeron_tables>to
enable memory-leak-free caching of bound functions, a small adaptation
of
your function results in:
// a map of obj -> (fun -> boundfun)
var _bound = new EphemeronTable();
var bang = function(obj) {
return Proxy.create({
get: function(_bang, func) {
var fn = obj[func];
// Still no isFunction...*sigh*
if (Object.prototype.toString.call(fn) === "[object Function]") {
var objBoundFuns = _bound.get(obj);
if (objBoundFuns && objBoundFuns.get(fn)) {
return objBoundFuns.get(fn); // bound function already existed
} else {
// create a new bound function
var bound = fn.bind(obj);
if (objBoundFuns) {
// obj already has bound functions, add it to the existing map
objBoundFuns.set(fn, bound);
} else {
// create a new mapping from obj -> bound functions of obj
objBoundFuns = new EphemeronTable();
objBoundFuns.set(fn, bound);
_bound.set(obj, objBoundFuns);
}
return bound; // return new bound fun
}
} else {
// not a function object, just return the deref
return fn;
}
}
})
};
node.addEventListener("click", obj!method);
> // actually removed without extra book-keeping or wrappers!
> node.removeEventListener("click", obj!method);
> [...]
> // ES3 impl lacks nice syntax:
> node.addEventListener("click", bang(obj, "method"));
> // works!
> node.removeEventListener("click", bang(obj, "method"));
>
Now consider (I renamed 'bang' to 'bind', as it seems more sensible):
node.addEventListener("click", bind(obj).method );
node.removeEventListener("click", bind(obj).method );
Granted, the overhead compared to dedicated syntax is probably significant.
Then again, the fact that this pattern avoids dedicated syntax while
remaining concise is also significant :-)
Cheers,
Tom
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss