# Elixir Idioms

> Elixir Idioms and Patterns

- Skill: `irahardianto/elixir-idioms` (Agent Skill)
- Install (CLI): `npx skillmds@latest add irahardianto/elixir-idioms`
- Raw SKILL.md: https://api.skillmd.com/api/skills/irahardianto/elixir-idioms/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: irahardianto (https://skillmd.com/u/irahardianto)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/irahardianto/elixir-idioms

---


## Elixir Idioms and Patterns

Elixir rewards immutability, pattern matching, and the OTP supervision model. Idiomatic Elixir = functional, fault-tolerant, process-oriented.

> Scope: Elixir coding idioms. Test naming: GEMINI.md § Testing Strategy.

### Pattern Matching

1. **Pattern match everything — function heads, case, with:**
   ```elixir
   def handle_result({:ok, task}), do: {:reply, task}
   def handle_result({:error, :not_found}), do: {:error, 404}
   def handle_result({:error, reason}), do: {:error, 500, reason}
   ```

2. **`with` for happy-path pipelines:**
   ```elixir
   with {:ok, user} <- fetch_user(user_id),
        {:ok, task} <- create_task(user, params),
        :ok <- notify(user, task) do
     {:ok, task}
   end
   ```

### OTP and Supervision

1. **GenServer for stateful processes:**
   ```elixir
   defmodule TaskCache do
     use GenServer

     def start_link(opts), do: GenServer.start_link(__MODULE__, %{}, opts)
     def get(pid, id), do: GenServer.call(pid, {:get, id})

     @impl true
     def handle_call({:get, id}, _from, state) do
       {:reply, Map.get(state, id), state}
     end
   end
   ```

2. **Supervision trees — "let it crash" philosophy.** Supervisors restart failed children.

3. **Never `try/catch` in normal flow** — let processes crash and restart cleanly.

### Pipe Operator

1. **`|>` for data transformation pipelines:**
   ```elixir
   tasks
   |> Enum.filter(&(&1.active))
   |> Enum.sort_by(& &1.priority, :desc)
   |> Enum.map(&TaskView.render/1)
   ```

2. **First argument must be the piped value.** Design APIs pipe-friendly.

### Naming

1. **snake_case** for functions, variables, atoms, module attributes.
2. **PascalCase** for module names.
3. **`?` suffix** for boolean functions: `active?/1`.
4. **`!` suffix** for functions that raise: `get!/1` (vs `get/1` returning `{:ok, _}`).

### Testing

1. **ExUnit:**
   ```elixir
   defmodule TaskServiceTest do
     use ExUnit.Case, async: true

     test "creates task with valid params" do
       {:ok, task} = TaskService.create(%{title: "Test", priority: :high})
       assert task.title == "Test"
     end
   end
   ```

2. **Mox for mock-based testing** (behaviour contracts).

### Formatting and Static Analysis

| Tool | Purpose | Command |
|---|---|---|
| `mix format` | Formatting | `mix format` |
| Credo | Linting | `mix credo --strict` |
| Dialyzer | Type checking | `mix dialyzer` |
| `mix deps.audit` | CVE scanning | `mix deps.audit` |

### Related
- Code Idioms and Conventions GEMINI.md § Code Idioms and Conventions
- Testing Strategy GEMINI.md § Testing Strategy
- Concurrency and Threading Principles @.gemini/skills/concurrency-and-threading-principles/SKILL.md

