LoginSignup
0
0

More than 5 years have passed since last update.

ElixirのGETTING STARTED(13. alias, require and import)をやってみた

Posted at

URL

試した環境

  • Ubuntu Server 14.04 LTS
  • Erlang/OTP 18
  • Elixir 1.0.4

alias, require and import

ソフトウェアと再利用するために、Elixirは3つディレクティブを提供している。
これらはレキシカルスコープを持っているためディレクティブと呼ばれる。

alias

alias は任意のモジュール名のためエイリアスを設定することができるようにする。特別な数学的な操作をするために、特定のリストの実装にMathモジュールを使うことを想像すると

def module Math do
    alias Math.List, as: List
end

ここで、Listへのどんな参照も自動でMath.Listへ展開される。このケースでは、オリジナルのListにアクセスしたいが、それはモジュール名にElixir.のプレフィックスをつけることによって可能になる。

List.flatten             #=> uses Math.List.flatten
Elixir.List.flatten      #=> usee List.flatten
Elixir.Math.List.flatten #=> uses Math.List.flatten

注意:Elixrで定義されているすべてもモジュールは、メインのElixirの名前空間内で定義される。しかし、利便性のために、それらを参照したい場合"Elixr"は省略可能である。

エイリアスはショートカットを定義する場合に頻繁に使われる。実際には、:asオプションないでaliasを呼び出すと、モジュール名の最後の部分が自動でaliasに設定される。

alias Math.List

下記と同様

alias Math.List, as: List

```ex
defmodule Math do
    def plus(a, b) do
        alias Math.List
        # ...
    end

    def minus(a, b) do
        # ...
    end
end

上記の例では、関数plus/2の内部でaliasを呼び出している。
このaliasは関数plus/2の内部でのみ有効。 minus/2には何の影響もない。

require

コードを生成するためのコードを書くメタプログラミングのためのメカニズムとしてマクロを提供している。

マクロはコンパイル時に展開され、実行されるコードのかたまり。
これは、マクロを使うためそのモジュールと実装がコンパイル時に利用可能であること保証する必要があることを意味する。これは、require ディレクティブで利用できる。

iex> Ingeger.is_odd(3)
** (UndefinedFunctionError) undefined function: Ingeger.is_odd/1 (module Ingeger is not available)
    Ingeger.is_odd(3)
iex> require Integer
nil
iex> Integer.is_odd(3)
true

Elixirでは、Integer.is_odd/1は、ガードとして使えるようにするためにマクロとして定義されている。これは、Integer.is_odd/1を呼び出すために、初めにIntegerモジュールを呼び出す必要があることを意味している。

一般的に、モジュール内でマクロを使いたい場合、そのモジュールを使う前にrequreする必要はない。ロードされていないマクロを呼びだそうとした場合エラーが起きる。 allias ディレクティブのように requireもレキシカルスコープであることに注意する。

import

他のモジュールで、完全修飾名を使うことなく関数やマクロに簡単にアクセスするために、 import を使う。
例えば、 何度もList モジュールの duplicate/2関数を使いたい場合、importすることができる。

iex> import List, only: [duplicate: 2]
nil
iex> duplicate :ok, 3
[:ok, :ok, :ok]

このケースでは、Listモジュールから duplicate/2 関数だけをimportしている。 :onlyはオプションだが、名前空間の内部にモジュールのすべての関数がimportされること防ぐために、このオプションを使う。
:expectは、そのリストの関数を除いたモジュールのすべての関数をimport するためにのオプションを提供する。

import:onlyオプションを与えることで :macros:functions をサポートする。例えば、すべてのマクロをimport するためには、次の記述する

import Integer, only: :macros

もしくは、すべての関数をimportするには、次のように書く

import Integer, only: :functions

import もレキシカルスコープ。これは関数の定義の内部にマクロや関数をimportできることを意味している。

defmodule Math do
    def some_funtion do
        import List, only: [duplicate: 2]
        duplicate(:ok, 10)
    end
end

上記の例では、インポートしたList.duplicate/2 は特定の関数内でしか見ることができない。 duplicate/2 はこのモジュール内の他のどんな関数からも利用できない。(もしくは、他のどんなモジュールからも)

モジュールをimportすると、自動でrequireすることに注意する。

Aliases

Elixirエイリアスは何で、どうやって表現しているのかという点を不思議におもうかもしれない。

Elixirでのエイリアスは、コンパイル時にatomに変換される大文字始まりの識別子( String, Keyword など)である。例えば、String エイリアスはデフォルトでは アトムの```:"Elixir.String"を変換している。

iex> is_atom(String)
true
iex> to_string(String)
"Elixir.String"
iex> :"Elixir.String" == String
true

alias/2 ディレクティブを使うことによって、簡単にエイリアスに変換することできる。

エイリアスは、Erlang VM (つまりElixir)でモジュールはatomとして表現されるためうまく動く。例えば、Erlangモジュールを呼び出すためのメカニズムは、

iex> :lists.flatten([1, [2], 3])
[1, 2, 3]

これは、モジュールの内部で与えられた関数を直接呼び出すことを許すメカニズムでもある。

iex> mod = :lists
:lists
iex> mod.flatten([1, [2], 3])
[1, 2, 3]

単に:listアトム上のflatten 関数を呼び出しているだけ。

Nesting

nestingとElixir上でそれがどのように動作するかを話す。
次のような例を考える。

defmodule Foo do
    defmodule Bar do
    end
end

上記の例は、2つのモジュール FooFoo.Bar を定義している。2つ目の関数は、同じレキシカルスコープにある限り Foo 内の Bar としてアクセスされる。

Bar モジュールを Foo モジュールの定義の外に移動した後、フルネーム( Foo.Bar )によって参照される必要がある。もしくは、上記で議論したように、alias ディレクティブの仕様をセットする必要がある。 Bar モジュールの定義は変更される。
このコードは上記の例と同じ。

defmodule Foo.Bar do
end

defmodule Foo do
    alias Foo.Bar, as: Bar
end

上記のコードは厳密には、次と同じ。

defmodule Elixir.Foo do
    def module Elixir.Foo.Bar do
    end
    alias Elixir.Foo.Bar, as: Bar
end

注意:Elixirでは、言語はすべてのモジュール名をatomに変換するため、Foo.Barモジュールを定義できるようになる前に、Fooモジュールを定義する必要はない。
モジュールの連続を定義することなく、任意にネストしたモジュールを定義できる。( Foo の定義や Foo.Bar の定義が初めになくても、Foo.Bar.Baz を定義できる。)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0