Hacker News new | past | comments | ask | show | jobs | submit login
JavaScript needs macros (meta2.tumblr.com)
52 points by andreyf on July 9, 2010 | hide | past | favorite | 22 comments



First let me say that as a long time Schemer, and one who did his graduate work on the semantics of macros, I am quite positively disposed towards macros. In theory, I think it'd be great for JavaScript to develop a macro system.

That said, macros are much harder to design, and much less well understood, than modules. Worse, macros in the context of a dynamically loaded global scope (e.g., JavaScript's global object) are a complete mess. The Scheme community is actually quite divided over this issue. Some portions of the Scheme community favor a much more dynamic semantics for macros, more in the Lisp tradition; others favor building macros on top of a more compilation-friendly semantics -- often, not coincidentally, built on top of a static module system. As an example, I'd recommend looking into the Racket programming language (formerly known as PLT Scheme), which has a built-in module system fairly similar to the one we've designed for Harmony -- and which leverages this module system to support one of the most powerful macro systems in the history of programming languages.

Next, one of the central aims of the module system design is to correct some of the past mistakes in JavaScript's scoping semantics. These are things that can't just be desugared away by simple macros. They require actual changes to the way whole JS programs are compiled and executed.

Finally, I'll add that it's easy to write a few code snippets on your blog and pretend it's a design, but it's nowhere near what is required to see a design all the way through. It's not even enough for the introductory text of a proposal. But if you have serious proposals to make, I'd encourage you to join es-discuss and make positive, substantive contributions to the conversation. However, I should warn you that well-designed macro systems are still very much the stuff of research.


Some portions of the Scheme community favor a much more dynamic semantics for macros, more in the Lisp tradition; others favor building macros on top of a more compilation-friendly semantics

Forgive my ignorance, but aren't Lisp's semantics very compilation-friendly? Doesn't macro expansion happen at read-time?

EDIT: I think that's the case for Common Lisp. By "the Lisp tradition" did you mean prior dialects?


you still can have dynamic semantics at read-time -- eg, does the macro-expand in reading the first form load new macros that affect the next form? Eg, in (progn (M) (M)), is it ever the case that the second M will dispatch to a different macro definition than the first M?

In the world of Common Lisp, yes. In the world of R6RS's more static semantics, no.


Facile snarky one-offs are sugary and lacking in intellectual nutrition, thus, popular.

Persistence, hard work, testing, all the sweat required to make something meaningful? Gross.


I cannot disagree enough.

There are plenty of JavaScript compilers that each have their own incompatible module systems. Adding another will only exacerbate what is already a major problem. JavaScript needs modules in the language to prevent fragmentation into what are effectively different source languages.


"And there are your modules, compatible with every browser instantaneously, without having to wait for IE12 to implement any JS dialects."

Maybe I misunderstood your point but.. IE12 needs to implement macro for this to work.. no?


IE12 needs to implement macro for this to work.. no?

No, the macros could be expanded into plain old JS by a pre-processor (maybe by your IDE on-save). Browsers only see the expanded code.


While traditionally IE has lagged on web standards, the IE9 pre-releases are (I believe) the first browser to implement ECMAScript 5.

We might not need to wait for IE12.


It's already pretty easy to do metaprogramming in JavaScript (as in use code to modify/create code) and it already supports both apply form and (the uglier) eval form so I don't really see what this brings to the table.

Been looking a little at clojure lately, both defmacro and the homoiconicity part of lisp is really powerful, but not very simple, compared to how you do metaprogramming in JavaScript.

So interesting post, but I don't think JavaScript needs more obscurity or the complexity of macros.


Types in Javascript? Blasphemy! :)

Jokes aside, you could easily write a preprocessor to do that. If the syntax you want is along the lines of

  keyword identifier { body }
  keyword identifier
it's just a matter of matching tokens, counting brackets and then replacing forms.

With that being said, the examples sounds like making busy-work for yourself. The "module" would still suffer from monkeypatching-related collisions (e.g. think document.getElementsByClassName in old versions of Prototype.js).

Also, javascript has both statements and expressions, so hypothetical macro-enhanced code like this

  var a = module A {}
would break depending on what "module" expands to.


The "module" would still suffer from monkeypatching-related collisions (e.g. think document.getElementsByClassName in old versions of Prototype.js).

I'm not sure what you mean. I'm thinking you would annotate the beginning of foo.xjs (extended JavaScript) with

   /*macros: modules.jsm*/
Then run the preprocessor, which will generate foo.js - a plain old JavaScript file.

The `s' in `defs' stands for "statement", so your example would throw the same error as "var a = if (x==4) ..."

    var a = module A {}
            ^
error: expected expression


   /*macros: modules.jsm*/
Whenever I see stuff intended for non-human consumption (doc-comments don't count, because they are just a standardization of a format so they can be more easily consumed by humans, and things like vim modelines don't count because they are not intended to change the meaning of the rest of the file) inside comment markers, I'm reminded of this old JWZ rant about the CDDB format http://www.jwz.org/doc/cddb.html


>> The "module" would still suffer from monkeypatching-related collisions

I mean that the module implementation will be a leaky abstraction because I can still do something like "Object.prototype.boom = true" inside a module and cause widespread brokenness. This encapsulation/robustness problem isn't something a simple macro can fix very easily, unfortunately, so both the module proposal that you linked to and your macro proposal sound like using a hammer as a screwdriver for that particular problem.

>> The `s' in `defs' stands for "statement"

Ah, that clears things up. I'd prefer something like a "defexpression" though, which would allow

  var a = module A {}
On a side note, var a = if (blah) would be cool to see too (well actually, I'd be more interested in var a = for(blah) ).


Ah, that clears things up. I'd prefer something like a "defexpression" though, which would allow

defexpression makes sense, too (but I'd call it `defe' - the more often you use something, the shorter it should be). For some reason, I had the intuition that it would be easier to add statements than expressions, but I don't see why it can't be as simple, as long as they start with some kind of unique token that can be considered a reserved keyword when parsing.


>> but I'd call it `defe' - the more often you use something, the shorter it should be

I was going to write that, but I got the feeling you'd wonder what the "e" stood for :)


counting brackets will get you in trouble if you have to read over strings.

there's no way around a real tokenization.


Crap, you're right. I completely forgot about strings and regexps (and E4X, for that matter) when I wrote that.


Frankly I think this is s stupid idea, macros are evil. I don't think we need them, the language is just fine without them.

But look at those examples.... they do nothing useful, they don't make the DOM behave, they don't enhance the language.

Use functions for recurring code!


I think using a pre-processor is MUCH better:

CoffeeScript: http://jashkenas.github.com/coffee-script/


You are going to get it, but not the way you think.

Google is working on native client, which is x86 code that executes inside the browser in a safe way (no idea how they pulled this of, but they did), much like Java script does today - chicken scheme, being a scheme, has macros and can compile to native code.

Vola - scheme, and macros, for client side programs.


macros cannot implement the whole proposal. but still some kind of macro system may be a worthwhile addition to, say, the closure compiler


Are people forgetting Knuth's earthshaking announcement about the next tex, called iTeX (jingle), that is going to make macros obsolete?




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: