Зіставлення зі зразком

Деякі частини цього перекладу можуть бути застарілими.
Декілька косметичних змін було додано до оригіналу цього уроку з останнього оновлення.

Зіставлення зі зразком (pattern matching) - важлива частина мови Elixir. Вона дозволяє зіставляти прості значення, структури та навіть функції. У цьому уроці ми почнемо вивчати як користуватися цією можливістю.

Зміст

Оператор зіставлення

В мові Elixir оператор = насправді є оператором зіставлення по аналогії зі знаком рівності в алгебрі. Його використання перетворює вираз на рівняння, і Elixir зіставляє ліву частину виразу з правою. У випадку успішного зіставлення буде повернуто розв’язане рівняння, інакше - виникне помилка:

iex> x = 1
1

Найпростіше зіставлення:

iex> 1 = x
1
iex> 2 = x
** (MatchError) no match of right hand side value: 1

Зіставлення з колекціями:

# Lists
iex> list = [1, 2, 3]
iex> [1, 2, 3] = list
[1, 2, 3]
iex> [] = list
** (MatchError) no match of right hand side value: [1, 2, 3]

iex> [1 | tail] = list
[1, 2, 3]
iex> tail
[2, 3]
iex> [2|_] = list
** (MatchError) no match of right hand side value: [1, 2, 3]

# Кортежі

iex> {:ok, value} = {:ok, "Successful!"}
{:ok, "Successful!"}
iex> value
"Successful!"
iex> {:ok, value} = {:error}
** (MatchError) no match of right hand side value: {:error}

Фіксуючий оператор

Ми вже розібрались, що оператор зіставлення робить присвоєння у тих випадках, коли ліва сторона зіставлення включає змінну. В деяких випадках переприсвоєння змінної є небажаним. У таких випадках використовується “фіксуючий оператор” ^.

Коли ми закріпляємо змінну з його допомогою - зіставлення відбувається з наявним значенням змінної, замість присвоювання нового значення:

iex> x = 1
1
iex> ^x = 2
** (MatchError) no match of right hand side value: 2
iex> {x, ^x} = {2, 1}
{2, 1}
iex> x
2

Версія Elixir 1.2 додала підтримку цього оператору в ключі асоціативних масивів і функціональні розгалуження:

iex> key = "hello"
"hello"
iex> %{^key => value} = %{"hello" => "world"}
%{"hello" => "world"}
iex> value
"world"
iex> %{^key => value} = %{:hello => "world"}
** (MatchError) no match of right hand side value: %{hello: "world"}

Приклад використання в функціональному розгалуженні:

iex> greeting = "Hello"
"Hello"
iex> greet = fn
...>   (^greeting, name) -> "Hi #{name}"
...>   (greeting, name) -> "#{greeting}, #{name}"
...> end
#Function<12.54118792/2 in :erl_eval.expr/5>
iex> greet.("Hello", "Sean")
"Hi Sean"
iex> greet.("Mornin'", "Sean")
"Mornin', Sean"