
Sweet.js – Hygienic Macros for JavaScript - ekzy
https://www.sweetjs.org/
======
jaywunder
The last thing the JS community needs is macros IMO. From what I've seen in
other languages, macros are difficult to maintain and document, and they add
syntax constructs to languages that aren't supported by code highlighters. The
difference between this and babel, is documentation. Babel is working off of a
specification of how the language should work, whereas I doubt someone will
document their macros as well as TC39 does the JS syntax

~~~
flavio81
Every language benefits from macros, and certainly JS.

------
eatonphil
Coming from a Scheme background, if there's one thing I can't believe we live
without in Javascript, it's macros. Hell even C has macros... I've looked at
Sweet.js a few times to add support for macros to the Linode Manager. Between
m4, the gcc preprocessor, and something native, this seemed like the easiest
potential sell. However, I've been turned off by how complicated this looks
compared to any of the other options and I'm not sure it actually even
supports the feature I want: allow some code to show up in "development" mode
but for that code to not even exist in the compiled output of "production"
mode. (The other feature that's just as important though is being able to wrap
shared code up in a single function that gets compiled in at compile time, but
I think Sweet.js supports that.)

~~~
ykler
Who uses m4? It has been around forever, but I have never really seen it used
except in autoconf. When I looked at it (a long time ago) it struck me as
really tricky and confusing, even more than lisp macros (but maybe on a par
with TeX). However, this was just a first impression -- I didn't go too deep.

~~~
kazinator
I once learned a lot about m4; more than twenty years ago. I remember all the
features it has, like redefining the delimiters for macros, diversions, for
loops and all that jazz.

So it's not due to lack of familiarity that I won't use it; it is simply
atrocious.

Recently I needed a preprocessor (featuring just simple if/ifdef/elif/endif)
in a Linux distro build system (Yocto). I didn't want to add anything new.

To avoid inflicting m4 on myself and everyone who has to interact with this in
the future, I wrote a simple awk script wrapped around cpp.

The tiny awk script implements this pipeline, which involves encoding and
decoding the input so that cpp never sees the syntax of the file:

    
    
      this is our                1                         1             this is our
      original                   2                         2  --> [dec]  original
      @ifdef FOO    --[enc]-->   #ifdef FOO  --[cpp]-->    6             file
      input                      4
      @endif                     #endif
      file                       6
    

this works with nearly any textual input. Your input can contain broken C
tokens and comments and whatnot.

I switched the # to @ to remind people that this isn't the C preprocessor, and
because # is a comment character in the preprocessed language, which could
look confusing.

------
couchand
The in-the-wild code I've seen that uses Sweet.js has been atrocious. Of
course I'm not saying that this is necessarily the case. I'd love to see some
real world examples whter this is used effectively.

~~~
btown
Separately, could you point to some examples of the bad Sweet code you've
seen? If it's anything like C macro misuse, it'll at the very least be
educational to see just how badly one can shoot oneself in the foot.

------
lmeyerov
We were looking into sweetjs for adding cross-module contracts to the
graphistry stack, but nixed the project when it became too much to generate
code that passed our basic linters. TS largely scratches that itch, so we've
been moving to that. I'm still hopeful though :)

------
lamlam
I personally prefer MetaScript [1] as it's comment based so JavaScript
highlighters/linters don't have issues with it.

It is also essentially JavaScript so no special syntax had to be learned.

[1]
[https://github.com/dcodeIO/MetaScript](https://github.com/dcodeIO/MetaScript)

------
longlho
this is already covered in basically any AST transform systems (babylon,
acorn, TS...)

~~~
adgasf
I believe that Babel lacks custom infix operators whilst Sweet.js provides
them.

~~~
btown
You're absolutely right; Babel's parser is very much hand-coded, and adding
syntax requires deep knowledge of the internals. Not impossible, but not for
the faint of heart. My dreams of having the safe navigation operator from
Coffeescript (a?.b?.c) must yet remain unfulfilled...

[https://github.com/babel/babylon/blob/master/src/parser/expr...](https://github.com/babel/babylon/blob/master/src/parser/expression.js#L461)

~~~
chocolateboy
> My dreams of having the safe navigation operator from Coffeescript (a?.b?.c)
> must yet remain unfulfilled...

Not for long:
[https://github.com/babel/babel/pull/5813](https://github.com/babel/babel/pull/5813)

~~~
btown
You just made my day :)

------
devdad
Can someone please explain macros, in an easy to grasp way?

~~~
coltonv
Say you're creating a programming language and you know everyone is going to
love it and use it. You add some nice features like if statements, switch
statements, and for loops which allow the people that use your language to
decide when certain code runs and shortens the syntax for common patterns.

Five years down the line your language is losing popularity fast, because all
the hip new languages have an "unless" statement which is the opposite of an
if statement. They have for-each loops, cond statements, and their if/else
statements return values, so you can write less code to do those common
patterns in those new languages than your language.

You rewind time 5 years using a time machine and this time, when you create
your langauge, you add all those cool features, only to realize in another 10
years your language has lost popularity because there's a new set features
they want, lambdas, argument piping, etc.

So this time when you go back in time, you add macros to your language. Macros
are bits of code that allow people using your language to write code that
produces more code. Now, you don't even have to write an unless statement, you
can let the community write one for you and release it as a package. Anyone at
any time can effectively add features to the language in their own project.

That sounds fantastic, and it often is, but macros need to not be abused. If a
developer writes a bunch of code using lots of his own macros in your
language, anyone reading that code later is going to be very confused seeing
that many language features that aren't in the language docs, because that
random developer wrote them himself. Functions are much more explicit than
macros, so if you can write whatever you're trying to write as a function
instead of a macro, you'll be better off. For every success story of a
language becoming easier to use because of macros, there's another story of a
different language becoming frighteningly complicated due to macro abuse.

------
alnitak
What would hygienic mean in this context?

~~~
Risord
Not C macro-like source code manipulation as dummy string but as more smart
structure like AST.

------
d--b
Also known as: 'how to build your own javascript dialect that you won't be
able to hire for'

