Skip to content

Instantly share code, notes, and snippets.

@Adzz
Last active April 30, 2019 13:32
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Adzz/a37ce7fe0228e385ff5ad49ebccdeab4 to your computer and use it in GitHub Desktop.
Save Adzz/a37ce7fe0228e385ff5ad49ebccdeab4 to your computer and use it in GitHub Desktop.
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