
JavaScript needs macros - andreyf
http://meta2.tumblr.com/post/787368639/javascript-needs-macros
======
dherman
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.

~~~
WalterGR
_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?

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

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

------
d0m
"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?

~~~
andreyf
_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.

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

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

~~~
andreyf
_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

~~~
lhorie
>> 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) ).

~~~
andreyf
_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.

~~~
lhorie
>> 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 :)

------
DjDarkman
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!

------
ptarjan
I think using a pre-processor is MUCH better:

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

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

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

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

