walkr

walkr

Collect modules that `use` some other module at compile time

Hello,

I need some help with the following problem (Bascially I want to store at compile time all modules using some other module, along with their opts).

defmodule Root do
  @modules %{} # Mapping from __MODULE__ to opts

  def __using__(opts) do
    quote do
        @opts unquote(opts)

        def hello(), do: "Hello from #{__MODULE__}"

        # How do I store __MODULE__ and its @opts
        # inside Root.@modules?
        # ...
    end
  end

  def modules_using_me: @modules
end

defmodule A do
  use Root, id: A1
end

defmodule B do
  use Root, id: B1
end

Then to get the modules __using__ Root I would call

iex> Root.modules_using_me()
%{A: [id: A1], B: [id: B1]}

OR

iex> SomeOtherModule.modules_using_root()
%{A: [id: A1], B: [id: B1]}

Could anyone give me some ideas? I already tried to accumulate into a Root attribute all other modules, but obviously it fails since Root module is already compiled.

Thank you!

Most Liked

christhekeele

christhekeele

As you observe, Root cannot know what modules use it at compile time, because it must first be compiled itself. Indeed, at compile time only module A could know if it used Root.

You can leverage module attributes to ask A which modules it has used—example code for that here.

Alternatively, since A knows what it’s used, you could inject that information into other modules that use A if you take control of its __using__ macro. This allows a module that uses both A and B to know what modules they respectively have used. This is pretty abstract and hard to explain—I have example code demoing the concept here.

mbuhot

mbuhot

Your problem sounds similar to protocol consolidation. You might find some inspiration in https://github.com/OvermindDL1/protocol_ex which has a custom mix compiler task that scans the beam files for modules that declare implemtations of a protocol.

OvermindDL1

OvermindDL1

I can easily add a function that returns all implementations of the given protocol too (I think I have it in a descriptor but it’s not really ‘public’ stuff?), but if that is the only feature you are needing then the normal elixir protocols already has that feature too.

But yeah, the scanner part itself could easily do that, copy it into your project and just have it be a compiler that generates the information necessary after everything else is already compiled. :slight_smile:

Where Next?

Popular in Questions Top

aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
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
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement