Reputation: 7506
I have a module called Interfaces:
defmodule Interfaces do
defmacro __using__(module) do
@module unquote(module) |> List.first |> elem(1)
defmacro expose(name) do
IO.inspect params, label: "Expanding macro with: "
IO.inspect @module, label: "I need this !!"
def unquote(name)() do
IO.puts "The function has been created with exposed name"
end
end
end
end
Another module called Interfaces.MyModule :
defmodule Interfaces.MyModule do
use Interfaces, for: Something.DefinedElseWhere
expose :plop
end
But at compile time I get
** (CompileError) lib/my_module.ex:6: undefined function expose/1
Upvotes: 1
Views: 1310
Reputation: 75840
I highly recommend that you read the Macros Guide on the official Elixir website. While what you're doing is possible (using quote
), it is not encouraged at all.
Macros should be simple and their functionality should be broken down further in other macros and methods if the need arises. One way to do that is to use the import
statement in your macro to import other macros that you need exposed in the final module:
defmodule Interface do
defmacro __using__(opts) do
quote(bind_quoted: [opts: opts]) do
import Interface
@interface_module Keyword.get(opts, :for)
end
end
defmacro expose(name) do
quote do
IO.inspect @interface_module, label: "I need this !!"
def unquote(name)() do
IO.puts "The function has been created with exposed name"
end
end
end
end
Now you can use it:
defmodule MyImplementation do
use Interface, for: AnotherModule
expose(:hello)
end
Here's another example from one of my projects, on how you should break down the implementation of large macros using helper functions and other macros.
Upvotes: 2