iexを便利にするハック集

# はじめに
Elixirを使ったプログラミングをする際は、デバッグや動作確認を目的としてiexを使用する機会が多いことと思います。この記事では、iexの使用を便利にするコマンドやツールを紹介します。

# iexを再起動せずコンパイルする

`iex -S mix` のようなコマンドでElixirのコードを実行した際、コードに変更を加えてから再度iexで動作を確認したいケースがあります。その場合、iexを一旦終了してからもう一度起動することが多いかと思いますが、[recompile/0](https://hexdocs.pm/iex/IEx.Helpers.html#recompile/0) を使うことで、iexの再起動なしにコンパイルすることができます。つまり、iexで次のコマンドを実行するだけです。

```
iex(1)> recompile
```

なお、 [r/1](https://hexdocs.pm/iex/IEx.Helpers.html#r/1) を使うことで、特定のモジュールのコードのみを再コンパイルすることも可能です。

# `v` で以前の出力結果を使う

[IEx.Helpers.v/1](https://hexdocs.pm/iex/IEx.Helpers.html#v/1) を使うことで、iexの最後に出力された値を取得することが可能です。そのため、以下のようなことができます。

```
iex(1)> 100 + 300
400

iex(2)> v - 34
366
```

また、 `IEx.Helpers.v/1` にマイナスの値 `n` 指定すると、最後からn番目の値を取り出すことができます。

```
iex(1)> 100 + 300
400

iex(2)> v - 34
366

iex(3)> v(-2)
400
```

# iexの履歴を保持する
通常、iexは終了するたびにその履歴が失われてしまいますが、次のようにフラグをセットすることで履歴を維持することができます。

```
export ERL_AFLAGS="-kernel shell_history enabled"
```

# aliasを有効にする
深いネストを持つmoduleをiexで複数回使用するようなケースでは、最初に `alias` を宣言することで入力が容易になります。

例えば、以下のようなmodule、functionを持っているとしましょう。

```elixir
defmodule Happy.World.Greeting do
  def hello(), do: :hello
end

defmodule Happy.World.Math do
  def plus(a, b), do: a + b
end
```

この場合、以下のように `alias` を宣言することで、moduleを省略して使用することができるようになります。

```sh
iex(1)> alias Happy.World.{Greeting, Math}      
[Happy.World.Greeting, Happy.World.Math]

iex(2)> Greeting.hello()
:hello

iex(3)> Math.plus(1, 2)
3
```

# `.iex.exs` でiex開始時の処理を定義する

iexを開始するディレクトリに `.iex.exs` を配置してiex開始時に実行したい処理を記述しておくと、iexはその内容を自動的にロードして評価します。例えば、以下のような `.iex.exs` ファイルを配置したとしましょう。

```elixir:.iex.exs
alias Happy.World.{Greeting, Math}

IO.puts("Start iex!!")
```

この状態でiexを開始すると、上記の内容が評価され、iexに反映されます。

```
$ iex -S mix
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.7.2) - press Ctrl+C to exit (type h() ENTER for help)
Start iex!!
iex(1)> Greeting.hello()
:hello
iex(2)> Math.plus(1, 2)
3
```

また、 `~/.iex.exs` を配置することで、グローバルな初期化処理を定義することもできます。

参考: [The .iex.exs file](https://hexdocs.pm/iex/IEx.html#module-the-iex-exs-file)

# `h` でドキュメントを確認する

[IEx.Helpers.h/1](https://hexdocs.pm/iex/IEx.Helpers.html#h/1) を使うことで、moduleやfunctionのドキュメントを出力することができます。以下の例を見てみましょう。

```
iex(1)> h Enum.join

                       def join(enumerable, joiner \\ "")                       

  @spec join(t(), String.t()) :: String.t()

Joins the given enumerable into a binary using joiner as a separator.

If joiner is not passed at all, it defaults to the empty binary.

All items in the enumerable must be convertible to a binary, otherwise an error
is raised.

## Examples

    iex> Enum.join([1, 2, 3])
    "123"
    
    iex> Enum.join([1, 2, 3], " = ")
    "1 = 2 = 3"
```

# `i` で情報を出力する

[IEx.Helpers.i/1](https://hexdocs.pm/iex/IEx.Helpers.html#i/1) を使うと、指定した変数、値の情報を出力することができます。以下の例を見てみましょう。

```
iex(1)> name = "Tsuyoshi"
"Tsuyoshi"

iex(2)> i name
Term
  "Tsuyoshi"
Data type
  BitString
Byte size
  8
Description
  This is a string: a UTF-8 encoded binary. It's printed surrounded by
  "double quotes" because all UTF-8 encoded codepoints in it are printable.
Raw representation
  <<84, 115, 117, 121, 111, 115, 104, 105>>
Reference modules
  String, :binary
Implemented protocols
  Inspect, IEx.Info, String.Chars, List.Chars, Collectable
```

# 複数行入力する

iexは、改行が行われた段階で複数行入力が必要かどうかを判断し、必要であれば自動的に複数行入力状態となります。

例えば以下の例では、1行目でStringの入力を開始しているものの、対となるダブルクォーテーションが無いために複数行入力となります。

```
iex(1)> message = "I am Tsuyoshi.
...(1)> I am happy.
...(1)> I don't know why.
...(1)> But I am happy."
"I am Tsuyoshi.\nI am happy.\nI don't know why.\nBut I am happy."
```

また、以下の例では `defmodule` の `do` に対応する `end` が1行目に無いため、複数行入力となります。

```
iex(1)> defmodule Happy do
...(1)>   def sayHappy, do: "I'm happy"
...(1)> end
{:module, Happy,
 <<70, 79, 82, 49, 0, 0, 3, 248, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 128,
   0, 0, 0, 13, 12, 69, 108, 105, 120, 105, 114, 46, 72, 97, 112, 112, 121, 8,
   95, 95, 105, 110, 102, 111, 95, 95, 7, ...>>, {:sayHappy, 0}}
```

しかし、1行だけで式の評価が可能になってしまう場合、自動的に複数行入力とはなりません。
例えば、以下のようなコードをiexで書きたいとしましょう。

```elixir
[1, 2, 3]
|> Kernel.++([4, 5])
|> Enum.map(fn n -> n + 5 end)
```

これをこのままiexで入力しようとしても、1行目だけで評価が終わってしまいます。

```
iex(1)> [1, 2, 3]                     
[1, 2, 3]
```

このような場合は、`(` を先頭に付けることで複数行入力を実現できます。(式全体を`()` で囲みます)

```
iex(1)> (
...(1)> [1, 2, 3]
...(1)> |> Kernel.++([4, 5])
...(1)> |> Enum.map(fn n -> n + 5 end)
...(1)> )
[6, 7, 8, 9, 10]
```

# 参考
[IEx](https://hexdocs.pm/iex/IEx.html)
[blackode/elixir-tips](https://github.com/blackode/elixir-tips)
[IEx Console Tips & Tricks](https://riptutorial.com/elixir/topic/1283/iex-console-tips---tricks)