В чём различие между = и == в Elixir?

В Elixir символы = и == выполняют совершенно разные функции, и их различие принципиально важно для понимания языка.

\= — оператор сопоставления с образцом (pattern matching)

В Elixir знак = не является оператором присваивания в классическом смысле (как в языках C, Java, Python). Это оператор сопоставления с образцом (pattern matching). Он проверяет, можно ли сопоставить значение справа с шаблоном слева. Если сопоставление возможно — переменная слева получает значение справа. Если нет — возникает ошибка MatchError.

Примеры:

x = 10 # x становится 10

10 = x # true, сопоставление удалось

11 = x # MatchError: нельзя сопоставить 11 и 10

Сопоставление работает и со сложными структурами:

{a, b} = {1, 2} # a = 1, b = 2
\[a, b\] = \[3, 4\] # a = 3, b = 4
{1, \_} = {1, :ok} # сопоставление успешно, второй элемент игнорируется

Можно использовать сопоставление с уже заданными значениями:

x = 1
^x = 1 # ОК, потому что ^x означает: значение должно быть равно 1
^x = 2 # MatchError

Особенность: если переменная слева ещё не была определена, она будет проинициализирована значением справа. Это может выглядеть как присваивание, но это именно сопоставление.

\== — оператор сравнения по значению

В отличие от =, оператор == сравнивает значения, а не выполняет сопоставление. Он проверяет, равны ли два выражения по значению, и возвращает true или false.

Примеры:

1 == 1 # true
1 == 2 # false
1 == 1.0 # true (так как Elixir считает их равными)

Elixir, как и Erlang, имеет сильную систему сравнения между типами, но при этом расширенную систему приведения типов при сравнении:

1 == 1.0 # true
1 === 1.0 # false (строгое сравнение по типу и значению)

Сравнение = и == — различия и применение

Оператор Назначение Возвращает значение Применение
\= Сопоставление с образцом Присваивает/проверяет шаблон В присвоении, в функциях с case, with, cond, аргументах функций
--- --- --- ---
\== Сравнение по значению true или false В логике, проверках условий
--- --- --- ---

Примеры:

x = 5 # Сопоставление: x становится 5
x == 5 # Сравнение: true
x == 6 # false
{a, b} = {1, 2} # Сопоставление
{1, 2} == {a, b} # true, значения равны

Если перепутать = и ==, можно получить неожиданные ошибки:

if x = 5 do
IO.puts("Да") # Это работает, но x всегда будет 5 — это не сравнение!
end
\# Правильно:
if x == 5 do
IO.puts("Да") # Это условие, которое можно оценивать
end