I have module that is mostly used as a namespace. Let us call it Bla
. There are other submodules, that have methods with specific functions to that submodule.
However, I want to have two options:
import main module Bla
and use all functions from submodules directly (not to write multiple imports separately)
import only specific submodule like Bla.Subbla
to use functions only from this module without importing functions from other submodules
This is what I have:
defmodule Bla do
defdelegate bla_func(text), to: Bla.Subbla
defdelegate bla_func(text, opts), to: Bla.Subbla
end
defmodule Bla do
def bla_func(text), do: Bla.Subbla.bla_func(text)
def bla_func(text, opts), do: Bla.Subbla.bla_func(text, opts)
end
What is the right way to do that? I have two options, but have no idea, maybe, there is much more better one. Are those two options equivalent? And which one is preferable? Is there any difference in performance?
A few differences I can think of:
defdelegate
your intent is very clear, you are just delegating the method to another method in another module. And that this is just a dumb forwarder.defdelegate
you cannot change the arguments
, whether be it the order, addition or removal of arguments. So, if all you really want is to forward the method call use defdelgate
as there is less scope to screw up.defdelegate
is not an option as you need to add more data to the forwarding function, in which case you don't really have an option.So, the bottomline is: if possible always use defdelegate
, you will avoid a few classes of bugs using it. e.g. below:
defmodule Greet do
def greet(name, greeting) do
IO.puts "#{greeting} #{name}"
end
end
defmodule DelegatedGreet do
defdelegate greet(name, greeting), to: Greet
end
defmodule BuggyGreet do
# scope for bugs like these
def greet(name, greeting), do: Greet.greet(greeting, name)
end
As @JustMichael told, it's good to use use
in this case. It does exactly what I need.
defmodule SomeModuleWhereINeedSubbla do
use Bla
useful_func # => Will print "Bla.Subbla.useful_func"
end
defmodule Bla do
defmacro __using__(_) do
quote do
import Bla.Subbla
end
end
end
defmobule Bla.Subbla do
def useful_func(), do: IO.puts "Bla.Subbla.useful_func"
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With