Elixirプログラムの構成を考える時にたまに便利なdefdelegate/2という関数があります。
Defines a function that delegates to another module.
Functions defined with defdelegate/2 are public and can be invoked from outside the module they're defined in, as if they were defined using def/2. Therefore, defdelegate/2 is about extending the current module's public API. If what you want is to invoke a function defined in another module without using its full module name, then use alias/2 to shorten the module name or use import/2 to be able to invoke the function without the module name altogether.
- 他のモジュールに委譲する関数を定義
- defdelegate/2で定義された関数はpublicであり、def/2で定義された場合と同様に、定義されたモジュールの外から呼び出すことが可能
論よりRun。
サンプルElixirプロジェクトを生成
$ mix new myapp
$ cd myapp
$ ls
README.md lib mix.exs test
lib/myapp.ex
の中身はこんなコードになっています。
defmodule Myapp do
@moduledoc """
Documentation for `Myapp`.
"""
@doc """
Hello world.
## Examples
iex> Myapp.hello()
:world
"""
def hello do
:world
end
end
IEx内でサンプルElixirプロジェクトを起動し、Myapp.hello/1
を実行してみます。
$ iex -S mix
iex> Myapp.hello()
:world
defdelegate/2を用いて委譲
lib/myapp.ex
の中身を変更します。
-
Myapp.Toukon
モジュールを作り、hello/0
を定義 -
defdelegate/2を用いて
Myapp.hello/0
をMyapp.Toukon.hello/0
に委譲
defmodule Myapp do
@moduledoc """
Documentation for `Myapp`.
"""
defdelegate hello, to: Myapp.Toukon
end
defmodule Myapp.Toukon do
@doc """
闘魂あいさつ
"""
def hello, do: "元気ですかーーーーッ!"
end
IEx.Helpers.recompile/1で再コンパイルし、Myapp.hello/1
をもう一度実行してみます。
iex> recompile
Compiling 1 file (.ex)
:ok
iex> Myapp.hello()
"元気ですかーーーーッ!"
Myapp
モジュールの使用者から見ると、Myapp.hello/0
は普通の関数ですが、実際の処理はMyapp.Toukon
モジュールへ移譲されています。
関数ドキュメントは委譲されない
あるElixirパッケージの開発をしている最中に気づきました。関数ドキュメントはできればコードの近くに置いておきたいものですが、defdelegate/2で別の関数から移譲された場合は関数ドキュメントがdelegate_to: Myapp.Toukon.hello/0
のようになります。自分のコードであればたいして問題にならないのですが、Elixirパッケージの開発ではpublic関数のドキュメントを読みやすくすることが重要です。
対策としては、単純にdefdelegate/2の真上に関数ドキュメントを書くしかなさそうです。
@doc """
闘魂あいさつ
## Examples
iex> Myapp.hello()
"元気ですかーーーーッ!"
"""
defdelegate hello, to: Myapp.Toukon
Elixirの実装にも何箇所か出てきます。
意外なことに、Webアプリ開発フレームワークのPhoenixでは1箇所だけしか使用されていないようです。
やっぱりdefdelegate/2の真上に関数ドキュメントが書かれています。
ご参考までに