elixir-patterns

Elixir Patterns and Conventions

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "elixir-patterns" with this command: npx skills add j-morgan6/elixir-claude-optimization/j-morgan6-elixir-claude-optimization-elixir-patterns

Elixir Patterns and Conventions

Pattern Matching

Pattern matching is the primary control flow mechanism in Elixir. Prefer it over conditional statements.

Prefer Pattern Matching Over if/else

Bad:

def process(result) do if result.status == :ok do result.data else nil end end

Good:

def process(%{status: :ok, data: data}), do: data def process(_), do: nil

Use Case for Multiple Patterns

Bad:

def handle_response(response) do if response.status == 200 do {:ok, response.body} else if response.status == 404 do {:error, :not_found} else {:error, :unknown} end end

Good:

def handle_response(%{status: 200, body: body}), do: {:ok, body} def handle_response(%{status: 404}), do: {:error, :not_found} def handle_response(_), do: {:error, :unknown}

Pipe Operator

Use the pipe operator |> to chain function calls for improved readability.

Basic Piping

Bad:

String.upcase(String.trim(user_input))

Good:

user_input |> String.trim() |> String.upcase()

Pipe into Function Heads

Bad:

def process_user(user) do validated = validate_user(user) transformed = transform_user(validated) save_user(transformed) end

Good:

def process_user(user) do user |> validate_user() |> transform_user() |> save_user() end

With Statement

Use with for sequential operations that can fail.

Bad:

def create_post(params) do case validate_params(params) do {:ok, valid_params} -> case create_changeset(valid_params) do {:ok, changeset} -> Repo.insert(changeset) error -> error end error -> error end end

Good:

def create_post(params) do with {:ok, valid_params} <- validate_params(params), {:ok, changeset} <- create_changeset(valid_params), {:ok, post} <- Repo.insert(changeset) do {:ok, post} end end

Immutability

All data structures are immutable. Functions return new values rather than modifying in place.

Always returns a new list

list = [1, 2, 3] new_list = [0 | list] # [0, 1, 2, 3]

list is still [1, 2, 3]

Guards

Use guards for simple type and value checks in function heads.

def calculate(x) when is_integer(x) and x > 0 do x * 2 end

def calculate(_), do: {:error, :invalid_input}

Anonymous Functions

Use the capture operator & for concise anonymous functions.

Verbose:

Enum.map(list, fn x -> x * 2 end)

Concise:

Enum.map(list, &(&1 * 2))

Named function capture:

Enum.map(users, &User.format/1)

List Comprehensions

Use for comprehensions for complex transformations and filtering.

Bad (multiple passes):

list |> Enum.map(&transform/1) |> Enum.filter(&valid?/1) |> Enum.map(&format/1)

Good (single pass):

for item <- list, transformed = transform(item), valid?(transformed) do format(transformed) end

Naming Conventions

  • Module names: PascalCase

  • Function names: snake_case

  • Variables: snake_case

  • Atoms: :snake_case

  • Predicate functions end with ? : valid? , empty?

  • Dangerous functions end with ! : save! , update!

Boolean Checks

Functions returning booleans should end with ? .

def admin?(user), do: user.role == :admin def empty?(list), do: list == []

Error Tuples

Return {:ok, result} or {:error, reason} tuples for operations that can fail.

def fetch_user(id) do case Repo.get(User, id) do nil -> {:error, :not_found} user -> {:ok, user} end end

Documentation

Use @doc for public functions and @moduledoc for modules.

defmodule MyModule do @moduledoc """ This module handles user operations. """

@doc """ Fetches a user by ID.

Returns {:ok, user} or {:error, :not_found}. """ def fetch_user(id), do: # ... end

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

phoenix-uploads

No summary provided by upstream source.

Repository SourceNeeds Review
General

elixir-essentials

No summary provided by upstream source.

Repository SourceNeeds Review
General

phoenix-liveview

No summary provided by upstream source.

Repository SourceNeeds Review