What is the difference between defdelegate and def with a call module function directly in Elixir

I have a module that is mainly used as a namespace. Let's call it Bla . There are other submodules that have methods with specific functions for this submodule.

However, I want to have two options:

1) import the main Bla module and use all functions directly from the submodules (do not write several imported separately)

2) import only a specific submodule of the Bla.Subbla type 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 this? I have two options, but I have no idea, maybe much better. Are these two options equivalent? And which one is preferable? Is there a difference in performance?

+5
source share
2 answers

A few differences that I can think of:

  • When you use defdelegate , your intentions are very clear, you simply delegate the method to another method in another module. And this is just a dumb forwarder.
  • With defdelegate you cannot change arguments , whether it is the order, addition or removal of arguments. So, if all you really need is to forward the method call with defdelgate , as there is less room for freezes.
  • In some cases, defdelegate not an option, since you need to add more data to the forwarding function, in which case you really have no option.

So bottom line: if possible always use defdelegate , you will avoid using multiple error classes. for example 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 
+4
source

As @JustMichael said, in this case it is useful to use use . He 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 
+2
source

All Articles