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.
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.
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.
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.
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.
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.
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.