Elixir入門(第十三章 alias, require, and import)
どうも、靖宗です。
今回は名前からするに外部ファイルの使い方とか名前空間とか?
# Alias the module so it can be called as Bar instead of Foo.Bar alias Foo.Bar, as: Bar # Require the module in order to use its macros require Foo # Import functions from Foo so they can be called without the `Foo.` prefix import Foo # Invokes the custom code defined in Foo as an extension point use Foo
順に追っていきましょう。
alias
これはなんとなく分かりやすいと思いますが、宣言したスコープ下でas:
以下として使用するって感じでしょうか。
defmodule Stats do alias Math.List, as: List # In the remaining module definition List expands to Math.List. end
このように利用すると、Statsモジュールの内部でListはMath.List
をさすように変えられます。
一応元々のListもElixir.List
として生きているようです。
おそらくグローバルで使える関数とかモジュールとかはElixir.
で利用できそう。
ショートカット(文字数を少なくする)としても使用されるようです。
また、alias Math.List
と書けばalias Math.List, as: List
と認識されるようです。冗長じゃなくて良い感じ。
スコープは定義したブロック下のみ。
defmodule Math do def plus(a, b) do alias Math.List # ... end def minus(a, b) do # ... end end
ここではMath.plus
の中だけです。
require
Elixirでのmacro
はメタプログラミング(コードを書くためのコード)用の機能だそうです。Cでいうdefineとかそのへん?
マクロはコンパイル時に展開されるようです。
とりあえずサンプルを見てみます。
iex> Integer.is_odd(3) ** (UndefinedFunctionError) function Integer.is_odd/1 is undefined or private. However there is a macro with the same name and arity. Be sure to require Integer if you intend to invoke this macro iex> require Integer Integer iex> Integer.is_odd(3) true
ElixirではInteger
というマクロが用意されていて、使用するときにはrequire Integer
が必要なようです。
デフォルトで用意されてないのは実行を少しでも早くする工夫なんでしょうか?
他のMacroの章で詳しく書かれてるみたいなんでとりあえずスルーします。
import
同じモジュールの関数を何回も使用する時など、関数名だけで実行したいときとかに使うっぽい。
iex> import List, only: [duplicate: 2] List iex> duplicate :ok, 3 [:ok, :ok, :ok]
この例ではList.duplicate/2
をimportしている。
:only
で指定の関数だけを、:except
で指定の関数以外をインポートできるようです。
また、:only
を用いてmacroやfunctionをインポートすることもできるようで。
import Integer, only: :macros import Integer, only: :functions
ますますmacroがなんなのか分からなくなってきた・・・
先に見た方がいいのかなぁ。
ちなみに、上の例でIntegerを使っているのでrequire
が必要っぽいが、import
はその辺は勝手にrequire
してくれる模様。
そしてこのimport
もスコープは宣言したブロックでのみ有効。
use
ぶっちゃけなんのこっちゃ分かりません。
テストのこと書いてるんでテストの時にでも見直します。
一応
defmodule Example do use Feature, option: :value end
と書くと
defmodule Example do require Feature Feature.__using__(option: :value) end
と展開されるマクロ、という事だそうです。
Understanding Aliases
Elixir内で表記されているエイリアス(StringとかKeyword)とかは、実はアトムだそうです。
iex> is_atom(String) true iex> to_string(String) "Elixir.String" iex> :"Elixir.String" == String true
エイリアスがアトムに展開されている理由はErlangのVMで動いてることに起因してるんだとか。
Erlangを知ってる人ならなるほどなっとくなのかな。
Module nesting
モジュールのネストの話。
一応モジュールはネスとしてかけるそうです。
大きくなりすぎたら管理しづらいからかな。
defmodule Foo do defmodule Bar do end end
String
が実際はElixir.String
である様に、モジュールも実際はElixir.Foo
とかになっているはず。
実際は下記のようになっているそうで。
defmodule Elixir.Foo do defmodule Elixir.Foo.Bar do end alias Elixir.Foo.Bar, as: Bar end
あまり気にしなくても良さそう?
Multi alias/import/require/use
Elixirのv1.2からは、さっきまで紹介してきたalias``import``require``use
をネストしたモジュールで一気に取り込む方法があるそうです。
alias MyApp.{Foo, Bar, Baz}
なるほど。
使うときになったらまた思い出せばいいかな。