38
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ElixirAdvent Calendar 2019

Day 12

iexを便利にするハック集

Last updated at Posted at 2019-12-11

はじめに

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

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

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

iex(1)> recompile

なお、 r/1 を使うことで、特定のモジュールのコードのみを再コンパイルすることも可能です。

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

IEx.Helpers.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を持っているとしましょう。

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を省略して使用することができるようになります。

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 ファイルを配置したとしましょう。

.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

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

IEx.Helpers.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 を使うと、指定した変数、値の情報を出力することができます。以下の例を見てみましょう。

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."

また、以下の例では defmoduledo に対応する 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で書きたいとしましょう。

[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
blackode/elixir-tips
IEx Console Tips & Tricks

38
14
2

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
38
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?