Last active
April 30, 2019 13:32
-
-
Save Adzz/a37ce7fe0228e385ff5ad49ebccdeab4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Test do | |
def thing() do | |
1+1 | |
end | |
defmacro my_macro do | |
quote do | |
1 + 1 | |
end | |
end | |
end | |
# Use alias wherever possible | |
defmodule Other do | |
alias Test | |
def foo do | |
Test.thing() | |
end | |
end | |
# If we want to use the macro though, Test needs to be compiled | |
# before our `Other` module (because macros get expanded at compile time). | |
# Our options are require or import. Prefer require, so you know where | |
# the functions you are using come from: | |
defmodule Other do | |
require Test | |
def foo do | |
Test.thing() | |
end | |
def bar do | |
Test.my_macro | |
end | |
end | |
# If you can't do that, or the number of functions you want to import is small, | |
# explicitly import the functions you need. You'll be able to see clearly non | |
# namespaced functions, then check for their names in the list of imports at the | |
# top. | |
defmodule Other do | |
import Test, only: [my_macro: 0] | |
def foo do | |
Test.thing() | |
end | |
def bar do | |
my_macro() | |
end | |
end | |
# Finally resort to importing all functions in rare cases. The only time | |
# I've not been able to use require (and _had_ to use import) is when we | |
# made a custom infix function. (You can define a limited number of them | |
# https://www.rodneyfolz.com/custom-infix-functions-in-elixir/ | |
# Finally the use macro has it's place if you are defining libraries, but | |
# I would avoid for your own code. A good example is ExUnit: | |
defmodule MyAppTest do | |
use ExUnit.Case | |
test "adds two numbers" do | |
end | |
end | |
# Having to write something like: | |
defmodule MyAppTest do | |
use ExUnit.Case | |
ExUnit.Case.test "adds two numbers" do | |
end | |
end | |
# would be clumsy, and the ExUnit maintainers would have to | |
# forever keep that test function in the ExUnit.Case module. | |
# A bad example of the using macro would be: | |
defmodule Test do | |
defmacro __using__(_) do | |
quote do | |
import Test | |
end | |
end | |
def thing() do | |
1+1 | |
end | |
defmacro my_macro do | |
quote do | |
1 + 1 | |
end | |
end | |
end | |
# you would do this: | |
defmodule Other do | |
use Test | |
def foo do | |
thing() | |
end | |
def bar do | |
my_macro | |
end | |
end | |
# Now it is not immediately clear where the functions `thing` and `my_macro` come from. | |
# Also, if you have multiple `use` macros at the top, it's even harder to discover which | |
# functions come from where. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment