Why does Elixir report UndefinedFunctionError
when calling a macro using Module.macroName
syntax in an .exs
file? I seem to able to call Macro only if I have another function that calls the macro and I call the function instead of macro.
Below code demonstrates this:
defmodule Sample do
defmacro doIt(expression) do
quote do
IO.puts unquote(expression)
end
end
def doFunc(e), do: doIt(e)
end
Sample.doFunc "Hello World via Function" # Works fine
Sample.doIt "Hello World from Macro!" # Gives error
Output
Hello World via Function
** (UndefinedFunctionError) undefined function: Sample.doIt/1
Sample.doIt("Hello World from Macro!")
(elixir) lib/code.ex:307: Code.require_file/2
The Elixir documentation example uses iex
, instead of calling macro in the .exs
file. Even above code, if we remove calls to Sample.doIt
and load it in iex
, and then call Sample.doIt
works fine.
E:\elixir>iex hello.exs
Hello World via Function
Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> require Sample
nil
iex(2)> Sample.doIt "Hello"
Hello
:ok
iex(3)>
If I try to require Sample
in my file above, like below
defmodule Sample
... rest of stuff as shown above ...
end
require Sample
Sample.doFunc "Hello World via Function"
Sample.doIt "Hello World from Macro!"
I get error
** (CompileError) hello.exs:11: module Sample is not loaded but was defined. This happens because you are trying to use a module in the same context it is defined. Try defining the module outside the context that requires it.
(stdlib) lists.erl:1352: :lists.mapfoldl/3
(stdlib) lists.erl:1353: :lists.mapfoldl/3
As usual you need to require a module before using its macros to signify to the compiler the order of compilation of the modules:
defmodule Other do
def run do
require Sample
Sample.doFunc "Hello World via Function"
Sample.doIt "Hello World from Macro!"
end
end
Other.run # => Hello World via Function
# Hello World from Macro!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With