apoorv-2204
Determining which module invoked a function( At Runtime)?
I have a module utils,which is supposed to be used by MOdule A, B,C,D… and so on. The issue is utils modules have lot of constants, constants specific to module A,B,C,D … . When i call module utils functions from module A, I want those functions to use constants defined in module A. same for B,C,D,… .What to use Import, use,etc.
So I can call module utils functions, so those util module functions can load constants depending upon which module has made the call.Opposed to passing as variable to the utils module functions. (since there is lot of functions).
So how to determine which module has invoked a function in another module at runtime. So I can leverage that information.
Most Liked
benstepp
It’s possible to do something similar with macros, but fair warning the general rule for macros is not to use them.
defmodule Util do
defmacro do_something() do
quote do
Util.do_something_with(@constant)
end
end
def do_something_with(constant) do
IO.puts("The constant is #{constant}")
end
end
defmodule A do
require Util
@constant 1
def test() do
Util.do_something()
end
end
defmodule B do
require Util
@constant 2
def test() do
Util.do_something()
end
end
defmodule C do
require Util
@constant 3
def test() do
Util.do_something()
end
end
A.test()
# The constant is 1
B.test()
# The constant is 2
C.test()
# The constant is 3
al2o3cr
I’m not going to even speculate along this line, because you shouldn’t do this.
Let’s talk about the underlying requirement instead.
Can you be more specific about what you mean by “having constants”? Modules don’t really “contain” anything - for instance, there’s no function in Module to get [Foo.Bar, Foo.Baz, Foo.Wat] given just Foo.
A common pattern for this is two parts:
- functions that accept the module as an additional argument beyond the “public” API
- a
usemacro that creates functions that include this extra argument in a user-controlled namespace
An example of this is Ecto.Repo.insert:
The underlying function is Ecto.Repo.Schema.insert, which accepts the repo as a first argument. In a default configuration with nobody calling put_dynamic_repo, that argument will be the module that said use Ecto.Repo.
In your case, you’d have a module in Utils that defines the __using__ macro and then use it in each of A, B, C, D like:
defmodule A.Utils do
use Utils, some_config: "specific to A"
end
# in other A code:
A.Utils.do_stuff("x", "y")
# which then calls
Utils.do_stuff(A, "x", "y")







