Hacker News new | ask | show | jobs
by alco 4434 days ago
Regarding 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

1 comments

> 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 :).

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