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


# URL
http://elixir-lang.org/getting-started/processes.html

# 試した環境
* Ubuntu Server 14.04 LTS 
* Erlang/OTP 18
* Elixir 1.0.4

# alias, require and import

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

# alias

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

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

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

```ex
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に設定される。

```ex
alias Math.List
```

下記と同様

```ex
alias Math.List, as: List
```

```alias```は、特定の関数内でエリアスを設定することが許されるレキシカルスコープであることに注意する。

```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```　ディレクティブで利用できる。

```ex
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することができる。

```ex
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 するためには、次の記述する

```ex
import Integer, only: :macros
```

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

```ex
import Integer, only: :functions
```

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

```ex
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"を変換している。

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

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

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

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

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

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

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

# Nesting

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

```ex
defmodule Foo do
    defmodule Bar do
    end
end
```

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

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

```ex
defmodule Foo.Bar do
end

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

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

```ex
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``` を定義できる。)