svilen

svilen

Author of Concurrent Data Processing in Elixir

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

kip

ex_cldr Core Team

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

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

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

kip

ex_cldr Core Team

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.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

We're in Beta

About us Mission Statement