11 ms·
Thanks for this; pretty much the response I was expecting but very well said. My opinion is that functions that take quoted code do actually do the 99% job of
by cursork 12y ago
Thanks for this; pretty much the response I was expecting but very well said.
My opinion is that functions that take quoted code do actually do the 99% job of macros pretty well. I also think creating completely new syntactic forms is fantastic for a solo project; but not so great when working in a team. So I'm left thinking what difference does it actually make. My general feeling is that I tend to write macros in Clojure just to deal with someone else's macros; i.e. macros 'layer' whereas functions compose.*
Incidentally, I've been curious about but never looked at Erlang's parse transforms because they have - in my mind at least - a big 'here be dragons' sign above them. Enough articles have warned me off to make me nervous. Would love to know more though.
* No idea if that makes sense to people. Hope so.
- alco 12y agoRegarding your point about cleaning up other people's macros. In Elixir macros are imported into local scope only when the user explicitly asks for it. Most libraries provide a `__using___` macro that can modify current scope. For instance, `use ExUnit.Case` allows you to write tests like this test "my test case" do assert funcall() == "value" end instead of this require ExUnit.Case ExUnit.Case.test "my test case" do ExUnit.Assertions.assert funcall() == "value" end So it basically imports a bunch of stuff for you, but only when you call `use ExUnit.Case`. The consensus in the community right now is to not get carried away with macros and DSLs. Even if your library provides a DSL, it should be based on a functional API that is mostly usable without macros. And lastly, remember that `use`, `require`, and `import` modify only the current lexical scope. I wrote this macro[1] that replaces the built-in `|>` operator with a version that prints its output to the console. You can `use PipeInspect` inside one function and only that function's body will get the overriden implementation of `|>`. Cheers. [1]: https://gist.github.com/alco/9956215 https://gist.github.com/alco/9956215
- cursork 12y ago> The consensus in the community right now is to not get carried away with macros and DSLs. Even if your library provides a DSL, it should be based on a functional API that is mostly usable without macros. Yup. But what people say and what people do is often not the same thing :).
- alco 12y agoSure. I just wanted to stress the point that macros are local in their scope. It's nothing like monkey-patching in Ruby where importing a module can change all divisions from floats to rational numbers.
- rvirding 12y agoErlang parse transforms give you access to the full AST of a whole module and it must return the full AST of a module. It is like a macro which operates on a module not on a form. They are very powerful but easy to get messed up in.