svilen
Dynamically add module functions in __using__ macro
I have a bunch of functions in a module, that I’d like to dynamically add to a __using__ macro:
defmodule A do
defmacro __using__(_opts) do
quote do
# Dynamically add
# def foo(), do: "Foo"
# and any other functions.
end
end
def foo(), do: "Foo"
end
My goal is to have the functions accessible on the original module, inject them into the module that’s using it via use and make them overridable:
I’m just starting with metaprogramming so I’d appreciate any solutions or pointers in the right direction. Thanks!
Marked As Solved
kip
If basically you want to delegate a bunch of functions to another module, have them available as public functions on the new module and also make them overridable then perhaps the following would work? Its not considered good practise to do defining lots of functions in a quote block.
defmodule A do
defmacro __using__(_opts) do
quote do
defdelegate foo(), to: A
defoverridable [foo: 0]
end
end
def foo(), do: "Foo"
end
defmodule B do
use A
end
Also Liked
jswny
I’m pretty sure you can just import the parent module of the __using__ macro with import A inside the macro. For example, the Phoenix 1.3 generators create the following DataCase module:
defmodule MyApp.DataCase do
using do
quote do
...
import MyApp.DataCase
end
end
def errors_on(changeset) ...
end
So, all of the MyApp.DataCase functions will be auto imported into the scope of any module which calls use MyApp.DataCase.
idi527
Kernel — Elixir v1.20.2 has an example similar to what you want:
defmodule A do
defmacro __using__(_opts) do
quote do
def foo, do: "Foo"
defoverridable [foo: 0]
end
end
end
defmodule B do
use A
def foo do
super() <> "Bar"
end
end
And then in the shell
iex(1)> B.foo()
"FooBar"
kip
import makes the functions from A available in module B but it doesn’t re-export them. Therefore functions in B can invoke the imported functions from A but you can’t call them from outside B. Its nothing to do with use, its how import works.
Overall, your last example isn’t a strong justification for use. Just import would be preferred because the intent is clearer. But I recognise your use case if presumably more complex that just import.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








