What is a JavaScript Macro?

9.9k views Asked by At

Recently I have seen people talk about the using of macros in JavaScript. I have no idea what that means and after looking up documentation on MDN I came up without any answer. So that leads me to my question …

What are JavaScript macros?
How/why are they used?
Is it a form of meta-programming?

Answers with examples and example code would be appreciated greatly.

2

There are 2 answers

2
Jean-Bernard Pellerin On

As has been posted in comments it's a macro system for javascript.

It's a way of defining text replacements in the "pre-processing phase". So you would define a macro and use it in your code, then run them both through sweet.js and the output would be code with text replacements.

example:

macro swap {
  rule { ($a, $b) } => {
    var tmp = $a;
    $a = $b;
    $b = tmp;
  }
}

var a = 10;
var b = 20;

swap (a, b)

After running this through sweet.js we get the expanded code:

var a$1 = 10;
var b$2 = 20;

var tmp$3 = a$1;
a$1 = b$2;
b$2 = tmp$3; 
0
jjhiggz On

I think the use case for this is more centered around frameworks and the likes. It's a more flexible way of saving lines of code than a function.

In JS, a function can basically either

  • Mathematically calculate something based off of it's inputs
  • Perform some kind of side effect on another variable within the scope of the function

But Macros are more flexible, it's like code that just takes in inputs and actually equates to text that can be compiled as regular code. It's a common feature in languages that prioritize code prettiness over code-traceability. A couple of notable examples are Ruby, Rust, and Elixir.

Here's an example of a ruby macro and what the equivalent code would look like in js.

In ruby you can do this to tell a class to have certain relationship methods in it's ORM

class Movie < ActiveRecord::Base
  has_many :reviews
end

In this case, saying has_many :reviews dumps a bunch of methods onto the Movie class. So because of that line you can call movie.reviews.

In TypeORM right now you could do something like

class Movie {
    @OneToMany(() => Review, review => review.movie)
    reviews: Review[];
}

If macros made it into js, you could clean this up to look more like

class Movie {
   oneToMany(Review, "reviews", "movie")
}

My guess is that this won't happen any time soon. IMO one of the things you lose with macros, is that it becomes less clear what your code actually does, I also have to imagine it would be a pretty big change for linters and type checkers. There's also other ways of dumping a bunch of functionality into an object or function.

For example in react hook form you can accomplish something similar using closures and spreading.

<input {...register("firstName")} placeholder="Bill" />