🫐

Elixir チートシート

2024/12/05に公開

この文書について

本稿は、もともと Zenn Book Phoenix LiveView 入門①: はじめの一歩の chapter 01「イントロダクション」の Section 2 であったものを Zenn Article として独立させたものです。

コメント

# Comment

変数

x = 1
x = x + 1
_unused_var = x + 1

アトム

:index
Index
:"123"

文字列

"Hello"
文字リスト

'Hello' のようにシングルクォートで囲むと文字リスト(charlist)になります。Erlang の関数を呼び出すとき以外には、ほぼ使われません。

文字列への式の埋め込み

name = "Alice"
message = "Hi, #{name}!"
IO.inspect(message) # => "Hi, Alice"

タプル

{"Alice", 1, true}

リスト

users = ["Bob", "Carol"]
users = ["Alice" | users]
users = users ++ ["David"]
IO.inspect(users) # => ["Alice", "Bob", "Carol", "David"]

マップ

data = %{"Alice" => 100, "Bob" => 20, "Carol" => 47}
score = Map.get(data, "Bob")
IO.inspect(score) # => 20

alice = %{name: "Alice", score: 100}
IO.inspect(alice.score) # => 100

シギル(シジル)

~s<Sum: #{1 + 1}!> # => "Sum: 2"
~S(Sum: #{1 + 1}!) # => "Sum: #{1 + 1}"
~w(alice bob carol) # => ["alice", "bob", "carol"]
~w/alice bob carol/a # => [:alice, :bob, :carol]
~r"[a-z][0-9a-z]*" # => 正規表現 [a-z][0-9a-z]*
シギルのデリミタ

~s<Sum: #{1 + 1}!> に含まれる <> のペアはシギルの始端と終端を表し、デリミタ(delimiters)と呼ばれます。

以下の 8 種類の文字ペアをシギルのデリミタとして使用できます:

  • <, >
  • {, }
  • [, ]
  • (, )
  • |, |
  • /, /
  • ", "
  • ', '

パターンマッチング

pair = {"Alice", 100}
{_name, score} = pair
IO.inspect(score) # => 100
user = %{name: "Alice", score: 100}
%{name: name} = user
IO.inspect(name) # => "Alice"

条件分岐

if x do
  "A"
end
if x do
  "A"
else
  "B"
end
cond do
  x == 1 -> "A"
  x == 2 -> "B"
  true -> "C"
end
case x do
  1 -> "A"
  2 -> "B"
  _ -> "C"
end

関数 Enum.map/2

numbers = [1, 2, 3]
results = Enum.map(numbers, &(&1 * 2))
IO.inspect(results) # => [2, 4, 6]

内包表記

numbers =
  for n <- [0, 1, 2, 3, 4] do
    n + 1
  end

IO.inspect(numbers) # => [1, 2, 3, 4, 5]
data = %{"Alice" => 100, "Bob" => 20, "Carol" => 47}

scores =
  for {_name, score} <- data do
    score
  end

IO.inspect(scores) # => [100, 20, 47]

範囲

numbers =
  for n <- 0..4 do
    n + 1
  end

IO.inspect(numbers) # => [1, 2, 3, 4, 5]

モジュール

defmodule Robot do
end

関数定義

defmodule Robot do
  def add(a, b) do
    a + b
  end
end

Robot.add(2, 3) # => 5
defmodule Droid do
  def add(a, b), do: a + b
end

Droid.add(2, 3) # => 5
アリティ

関数の引数の個数をアリティ(arity)と呼びます。

上記の関数を API ドキュメント等で参照するとき、Robot.add/2 のように表記します。末尾の /2 はアリティを示します。

マクロ

コンパイル時に行われる一連の処理に名前を付けたものをマクロと呼びます。本巻では(おそらく本シリーズを通じて)マクロを定義する方法について説明しません。しかし、定義済みのマクロを呼び出す機会は頻繁にあります。

関数と同様にマクロは特定のモジュールに所属します。マクロの呼び出し方は関数と同じです。

パイプ演算子

str = "Alice Bob Carol"

result =
  str
  |> String.split(" ")
  |> Enum.map(fn name -> String.first(name) end)
  |> Enum.join("-")

IO.inspect(result) # => "A-B-C"

無名関数

add = fn a, b -> a + b end
r = add.(2, 3)
IO.inspect(r) # => 5

& 記法

add = &(&1 + &2)
r = add.(2, 3)
IO.inspect(r) # => 5
names = ~w(Alice Bob Carol)
initials = Enum.map(names, &String.first/1)
IO.inspect(initials) # => ["A", "B", "C"]

ガード

defmodule Robot do
  def increment(a, b) when b > 0, do: a + b
  def increment(a, _), do: a
end

Robot.increment(2, 3) # => 5
Robot.increment(2, -3) # => 2

モジュール属性

defmodule Robot do
  @name "Alice"

  def greeting do
    "Hi, my name is #{@name}!"
  end
end

IO.inspect(Robot.greeting()) # => "Hi, my name is Alice!"
定数としてのモジュール属性

モジュールの定義中で @name "Alice" のように書くと、name という名前のモジュール属性"Alice" という値が設定されます。モジュール属性は、コンパイル時に「定数」として展開されます。

@name = "Alice" のように等号(=)を使わない点に注意してください。

@doc のようないくつかのモジュール属性には特別な役割が与えられています。

構造体

defmodule User do
  defstruct name: nil, score: 0
end

u = %User{name: "Alice", score: 100}
IO.inspect(u.name) # => "Alice"
u = %{u | score: 200}
IO.inspect(u.score) # => 200
構造体とは

構造体とは、マップと同様に複数個の値を集合として扱うためのデータ型です。

構造体の各値にはユニークなキーが割り当てられます。構造体のキーはフィールドとも呼ばれます。

マップとは次の3点で異なります。

  • 構造体のキーは必ずアトムである。
  • 構造体にキーを追加できない。
  • 構造体からキーを削除できない。

構造体はモジュール定義の中で defstruct マクロにより定義されます。上記の例ではフィールド namescore を持つ構造体を定義しています。フィールド name のデフォルト値は nil, フィールド score のデフォルト値は 0 です。モジュール User で定義された構造体は、「User 構造体」と呼ばれます。

Discussion