Hello, I'm Nick Fitzgerald. This is my weblog. You can also check out my shared items from Reader and code on GitHub. Feel free to contact me about whatever.
September 21st, 2009
Edit: I submitted this post to Hacker News to get some feedback and there is some small discussion over there.
It seems people other than myself would like to have macros in JavaScript, which makes me happy. Not as happy as if macros were part of the ECMAScript standard, but it is nice to know I'm not alone.
I have been wondering about how macros in JavaScript would work for a while now, and since I had the day off from work today, I made a little proof-of-concept.
<html>
<head>
<style>
.pass {
color:green;
}
.fail {
color:red;
}
</style>
</head>
<body>
<ul id="results">
</ul>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
</script>
<script type="text/macroJS" id="macroJS">
-> assert(val, desc) {
<< $("#results").append(
"<li class=\"" + (~> {
<< !!val ?
"pass" :
"fail";
}()) + "\">" + desc + "</li>");
}
assert(typeof(~> {}) === "function",
"The '~>' syntax is a function with one argument called '_'.");
assert(typeof(->() {}) === "function",
"The '->' syntax is short for 'function'.");
assert((~> {
<< true;
}()), "The '<<' syntax is short for 'return'.");
assert((~> {
var a = "broken";
unless (false) {
a = "works";
}
<< a === "works";
}()), "'Unless' is the opposite of 'if'.");
</script>
<script type="text/javascript">
eval((function (str) {
return str.replace(/unless[\s]*?\(/g, "if (!")
.replace(/->/g, "function")
.replace(/~>/g, "function (_)")
.replace(/<</g, "return");
}($("#macroJS").html())));
</script>
</body>
</html>
Of course, when you run the demo the descriptions in the assertions have been manipulated by the macro-expansion as well as the actual code, but the point is that the macros expand successfully.
I took the "->" and "~>" syntax from this interesting blog post, I came up with the "<<" syntax all by myself (!), and the "unless" statement is from the example in Peter Michaux's blog post.
The macros here are very simple syntax-hacks, and just a proof-of-concept, but I think it shouldn't be too hard to expand on these further. Since the replace method can take a function as a second argument that can access the grouped matches in your regexes, it is very possible to create more powerful macros.
Finally, would I consider using this technique for the code that I write at work or for my side projects? No, because the pain of debugging from inside an eval outweighs the potential benefits in this case. If you really want macros in JavaScript, your best bet is probably ParenScript.
On July 23rd, 2010
On July 19th, 2010
On July 5th, 2010
On June 29th, 2010
On June 25th, 2010
On June 21st, 2010
On June 2nd, 2010
On May 20th, 2010
On May 19th, 2010
On May 2nd, 2010
blog comments powered by Disqus