Перейти до основного вмісту

Зіставлення по зразку в Elixir

Зіставлення по зразку (pattern matching) — це одна з найпотужніших можливостей мови Elixir. Це не просто присвоєння значень змінним, а механізм для деструктуризації даних та перевірки їхньої структури.

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

В Elixir оператор = — це не оператор присвоєння, а оператор зіставлення. Він намагається зробити ліву частину рівною правій.

# Проста змінна
x = 1
# x тепер дорівнює 1

# Зіставлення зі значенням
1 = x
# Це працює, тому що x = 1

# Помилка зіставлення
2 = x
# ** (MatchError) no match of right hand side value: 1

Зіставлення зі списками

Зіставлення дозволяє витягувати елементи зі списків:

# Зіставлення всього списку
[a, b, c] = [1, 2, 3]
# a = 1, b = 2, c = 3

# Виділення голови та хвоста
[head | tail] = [1, 2, 3, 4]
# head = 1, tail = [2, 3, 4]

# Ігнорування елементів
[_, second, _] = [10, 20, 30]
# second = 20

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

Кортежі часто використовуються для зіставлення, особливо для обробки результатів функцій:

# Зіставлення з кортежем
{status, result} = {:ok, "Success"}
# status = :ok, result = "Success"

# Обробка помилок
case File.read("file.txt") do
  {:ok, content} -> 
    IO.puts("Вміст: #{content}")
  {:error, reason} -> 
    IO.puts("Помилка: #{reason}")
end

Зіставлення з картами (maps)

Карти дозволяють витягувати значення за ключами:

# Витягування значень
%{name: name, age: age} = %{name: "Іван", age: 30, city: "Київ"}
# name = "Іван", age = 30

# Часткове зіставлення
%{name: name} = %{name: "Марія", age: 25}
# name = "Марія" (age ігнорується)

# Зіставлення з конкретним значенням
%{status: :active, user: user} = %{status: :active, user: "admin"}
# Спрацює тільки якщо status = :active

Пін-оператор (^)

Використовується для зіставлення з існуючим значенням змінної замість створення нової прив'язки:

x = 1

# Без пін-оператора (перезапис)
x = 2
# x тепер дорівнює 2

# З пін-оператором (зіставлення)
x = 1
^x = 1  # OK
^x = 2  # MatchError

# Практичне застосування
[^x, y] = [1, 2]  # OK, y = 2
[^x, y] = [2, 3]  # MatchError

Зіставлення у функціях

Зіставлення по зразку особливо корисне при визначенні функцій з різними варіантами вхідних даних:

defmodule Calculator do
  # Зіставлення за значенням
  def operate(:add, a, b), do: a + b
  def operate(:subtract, a, b), do: a - b
  def operate(:multiply, a, b), do: a * b
  
  # Зіставлення зі структурами
  def process_user(%{name: name, admin: true}) do
    "Адміністратор: #{name}"
  end
  
  def process_user(%{name: name}) do
    "Користувач: #{name}"
  end
  
  # Рекурсія зі списками
  def sum([]), do: 0
  def sum([head | tail]), do: head + sum(tail)
end

Охоронці (Guards)

Охоронці дозволяють додавати додаткові умови до зіставлення:

defmodule Numbers do
  def check(x) when x > 0, do: "Позитивне"
  def check(x) when x < 0, do: "Негативне"
  def check(0), do: "Нуль"
  
  def adult?(age) when age >= 18, do: true
  def adult?(_), do: false
  
  # Комбіновані охоронці
  def classify(x) when is_integer(x) and x > 0, do: "Натуральне"
  def classify(x) when is_float(x), do: "Дробове"
end

Практичні приклади

Приклади реального використання зіставлення:

# Обробка HTTP-відповідей
case HTTPoison.get(url) do
  {:ok, %{status_code: 200, body: body}} ->
    {:ok, body}
  {:ok, %{status_code: 404}} ->
    {:error, :not_found}
  {:error, reason} ->
    {:error, reason}
end

# Парсинг команд
def handle_command(["create", name]) do
  create_item(name)
end

def handle_command(["delete", id]) when is_binary(id) do
  delete_item(id)
end

def handle_command(_) do
  {:error, "Невідома команда"}
end

Переваги зіставлення по зразку

  • Читабельність: код стає більш декларативним і зрозумілим
  • Безпека: компілятор попереджає про неповні зіставлення
  • Деструктуризація: легко витягувати дані зі складних структур
  • Елегантність: замінює багато if/else конструкцій
  • Функціональний стиль: природно поєднується з рекурсією та незмінністю

Зіставлення по зразку — це фундаментальна концепція Elixir, яка робить код більш виразним та надійним.

Коментарі

Популярні публікації

Дамп бази даних Postgresql локально

Що потрібно встановити локально (Ubuntu) Встанови клієнтські утиліти PostgreSQL: pg_dump , psql , pg_restore . sudo apt update sudo apt install postgresql-client Кроки міграції Ідея: не зберігати дамп на серверах. Зробити дамп з віддаленого сервера на свій локальний ПК, потім передати його на новий сервер і там відновити. 1) Створення дампу з віддаленого сервера локально pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB -f dump_file.dump Пояснення ключів: -h (хост), -U (користувач), -Fc (custom format), -d (БД), -f (вихідний файл локально). 1.1) Варіант з розбиттям на частини (якщо треба) pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB | split -b 10G - dump_file.dump.part_ Це створить локально файли типу dump_file.dump.part_aa , dump_file.dump.part_ab тощо. 2) Передача дампу на новий сервер Один файл: scp dump_file.dump NEW_USER@NEW_SERVER_IP:/tmp/ Або частинами: scp dump_file.dump.part_* NEW_USER@NEW_SERVER_IP:/tmp/ 3) Збирання файл...

Основи Next.js

Що таке Next.js? Next.js — це прогресивний фреймворк для розробки веб-застосунків на основі React. Він розширює можливості React, додаючи готову інфраструктуру для Server-Side Rendering (SSR), генерації статичних сторінок, маршрутизації через файлову систему, а також можливість створювати backend-ендпоінти прямо в проєкті. Чому він став популярним? Next.js швидко здобув популярність завдяки тому, що пропонує: SEO-дружні сторінки завдяки SSR / SSG; швидкий перший рендер (First Page Load); просту маршрутизацію без налаштування; розгортання в один клік через Vercel; вбудовану оптимізацію зображень та продуктивності. Чим відрізняється від класичного React У класичному React ми отримуємо лише клієнтську бібліотеку для побудови UI-компонентів. Усе інше (SSR, маршрути, API) треба налаштовувати вручну або через сторонні бібліотеки (наприклад, React Router, Redux, Express, etc.). Next.js — це уже повноцінний фреймворк. Він одразу має: серверний рендеринг...

ООП у TypeScript

Короткий вступ TypeScript додає статичну типізацію поверх JavaScript і підтримує класичні концепти ООП: класи , успадкування , інтерфейси , інкапсуляцію , поліморфізм та абстракції . Нижче — практичні приклади та пояснення. Класи — декларація, конструктор, властивості та методи class Person { public name: string; private age: number; protected email?: string; // необов’язкове static species = 'Homo sapiens'; constructor(name: string, age: number, email?: string) { this.name = name; this.age = age; this.email = email; } public greet(): string { return `Hi, I'm ${this.name}.`; } private getBirthYear(currentYear: number): number { return currentYear - this.age; } } const p = new Person('Ivan', 30, 'ivan@example.com'); console.log(p.greet()); // console.log(p.age); // помилка: 'age' приватне console.log(Person.species); Успадкування і перевизначення (extends, super) class Employee extends Person { ...

Створення проєкту на TypeScript, модулі

Крок 1. Ініціалізація проєкту Спочатку створимо нову теку та ініціалізуємо Node.js-проєкт за допомогою npm : mkdir my-typescript-app cd my-typescript-app npm init -y Крок 2. Встановлення TypeScript Додаємо TypeScript як dev-залежність: npm install --save-dev typescript ts-node @types/node - typescript — компілятор TypeScript - ts-node — дозволяє запускати TS-файли без попередньої компіляції - @types/node — типи для стандартних Node.js API Крок 3. Створення файлу tsconfig.json Ініціалізуємо конфігурацію TypeScript: npx tsc --init Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020", // Версія JS у вихідному коді "module": "CommonJS", // Система модулів (для Node.js) "rootDir": "src", // Вхідна папка з TypeScript-кодом "outDir": "dist", // Куди компілюється код JS "str...

Інструменти для роботи з Node.js

Що таке npm? npm (Node Package Manager) — це офіційний пакетний менеджер для Node.js . Він дозволяє: Встановлювати сторонні бібліотеки та фреймворки Керувати залежностями проєкту Запускати скрипти (команди) через package.json Приклад ініціалізації проєкту з npm npm init -y Файл package.json (скорочений приклад) { "name": "my-project", "version": "1.0.0", "scripts": { "start": "ts-node src/index.ts", "build": "tsc" }, "dependencies": { "express": "^4.18.0" }, "devDependencies": { "typescript": "^5.0.0", "ts-node": "^10.0.0" } } Що таке tsconfig.json? tsconfig.json — це файл конфігурації для компілятора TypeScript, який визначає, як слід компілювати код. Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020...