Hacker News new | ask | show | jobs
by lectrick 4102 days ago
> I strongly dislike macros that can hide in code. I get really frustrated when I open a source file and see (foo ...) and can’t tell whether it’s a function or a macro until I read documentation.

Well... that's just, like, your opinion, man.

Seriously though. In Elixir, for example, much of the language itself is implemented via its own macros, which demonstrates a certain nice extensibility. If Elixir followed this same pattern, it would get really annoying really quickly, as even simple if statements would require a leading slash.

Also, I preferred "unf" ;)

2 comments

Yep, it's my opinion, and that's why I put it into the design. Lots of language design comes from opinions. I hope it's borne out. FWIW it's the same approach Rust has taken, where macros have to end with a ! to make them visually distinct.
That might be because Rust might not eat its own dogfood in that department, and build some of its own functionality out of its macro system.

But I can see just "knowing" at a glance if it's a macro or not.

I think the answer would basically be determined by how much of the language itself uses its own macro system AND what type of macro system it actually is. If it's significant, having special syntax would just look weird.

Rust does eat its own dogfood with regard to macros, and over time has steadily replaced former language-level features like `log` and `panic` with macros. Syntactic distinction is a philosophical choice in service of making costs more explicit (and while it's true that functions can hide behavior, overuse of macros can trigger enormous code bloat, such as the `regex!` macro which compiles your regex into a state machine).

(There are also valid technical reasons for requiring syntactic distinction, as the sheer flexibility of Rust's macros in their ability to create new syntax run the risk of making it a nightmare to parse if you remove the unambiguous ability of the compiler to drop into macro-parsing mode. These challenges aren't insurmountable, just very hairy.)

If you see (foo ...) but don't actually know what foo does, it doesn't matter all that much whether it is a function or an operator. Even if you know it's a function, that just tells you how the arguments are evaluated; but not what happens with those values. Untold effects could hide behind a function call.
This is also true for Racket. The language is basically all macros built on top of each other. While this superficial distinction between macros and other constructs serves a purpose, I think that purpose is largely misguided and invented.

What is the need for knowing if it's a macro or not when you could just know how it works (what'll it spit out / do?)?

While I do believe in limiting stuff for the sake of simplicity, this notation will actually burden the developer into not using the macro system fully, simply because someone wants there to be a non-forced distinction between macros and other constructs in the code.