# Elixir by Example > Small, annotated Elixir programs, each executed on Elixir 1.20.5 / OTP 29 when the site is built, so code and output are verified. Every page has a plain-source twin: append `.exs` to its URL. The whole site as one file: https://elixirbyexample.com/llms-full.txt Conventions: column-0 `#` comments are explanations; everything else is runnable code. Notes starting with "Pitfall" describe mistakes people and coding agents commonly make. ## Core Elixir The language itself: data, pattern matching, functions, modules and protocols. - [Hello World](https://elixirbyexample.com/core/hello-world.exs): Our first program prints the classic message. Save it as hello-world.exs and run it with elixir hello-world.exs. No project or compile step needed: .exs file... - [Values](https://elixirbyexample.com/core/values.exs): Elixir has a handful of basic value types. Integers have arbitrary precision, so they never overflow. - [Atoms](https://elixirbyexample.com/core/atoms.exs): An atom is a constant whose value is its own name. Atoms label things: statuses, options, message tags. - [Strings and Binaries](https://elixirbyexample.com/core/strings.exs): Strings are UTF-8 encoded binaries, written in double quotes. - [Lists and Tuples](https://elixirbyexample.com/core/lists-and-tuples.exs): Lists are singly linked. Prepending is O(1); appending or indexing is O(n). - [Maps](https://elixirbyexample.com/core/maps.exs): Maps are Elixir's key-value data structure. Any value can be a key, and keys are unordered. - [Keyword Lists](https://elixirbyexample.com/core/keyword-lists.exs): A keyword list is a list of {atom, value} tuples, with special syntax. It's how Elixir passes options. - [Pattern Matching](https://elixirbyexample.com/core/pattern-matching.exs): = is the match operator. The left side is a pattern; Elixir makes it match the right side, binding variables along the way. - [case, cond and if](https://elixirbyexample.com/core/case-cond-if.exs): case matches a value against patterns, top to bottom. Clauses can have guards. - [Anonymous Functions](https://elixirbyexample.com/core/functions.exs): Anonymous functions are values. Create them with fn, call them with a dot. - [Modules and Named Functions](https://elixirbyexample.com/core/modules.exs): Named functions live in modules. def makes a public function, defp a private one. - [Guards](https://elixirbyexample.com/core/guards.exs): Guards add conditions to pattern matches with when. They work in function heads, case, fn and comprehensions. - [Recursion](https://elixirbyexample.com/core/recursion.exs): Elixir has no for/while loops that mutate a counter. Repetition is recursion: a function that calls itself on a smaller problem, with one clause for the base... - [The Pipe Operator](https://elixirbyexample.com/core/pipe-operator.exs): The pipe operator |> takes the value on its left and passes it as the first argument of the call on its right. Nested calls read inside-out: - [Enum](https://elixirbyexample.com/core/enum.exs): Enum is the toolbox for anything enumerable: lists, maps, ranges, MapSets and more. Its functions are eager: each one walks the whole collection and returns ... - [Comprehensions](https://elixirbyexample.com/core/comprehensions.exs): A comprehension (for) maps, filters and combines enumerables in one expression. It returns a list by default. - [Streams](https://elixirbyexample.com/core/streams.exs): Stream functions look like Enum functions but are lazy: they build a recipe instead of a result. Nothing runs until an Enum function consumes it. - [Structs](https://elixirbyexample.com/core/structs.exs): A struct is a map with a fixed set of keys, defined in a module and named after it. It gives a shape a name, defaults, and compile-time key checking. - [Protocols](https://elixirbyexample.com/core/protocols.exs): A protocol is polymorphism for data: one function name, a separate implementation per type. It's how tostring/1, inspect/1 and Enum work on so many types. - [with](https://elixirbyexample.com/core/with.exs): Many Elixir functions return tagged tuples: {:ok, value} on success and {:error, reason} on failure. with chains several such steps and stops at the first on... - [Errors and Tagged Tuples](https://elixirbyexample.com/core/errors.exs): Elixir has two ways to signal failure. Expected failures (a missing file, bad user input) are return values: {:ok, value} or {:error, reason}. - [Sigils](https://elixirbyexample.com/core/sigils.exs): Sigils are literals that start with ~, a letter, and a pair of delimiters. They're shortcuts for common kinds of text and data. ### Project: Build a key-value store - [About this project](https://elixirbyexample.com/core/kv.md): Concept pages show one idea at a time. Real programs combine them, so each track ends with a project that does exactly that. Across the whole site we build o... - [A map is already a store](https://elixirbyexample.com/core/kv-01-a-map-is-a-store.exs): Across these steps we build KV, a small key-value store, and keep growing it: concurrent, supervised, cached in ETS, expiring keys, and later distributed acr... - [Give it a proper type](https://elixirbyexample.com/core/kv-02-a-proper-type.exs): Step 1's store was a bare map, so nothing stopped a caller from passing any map, or storing keys we never meant to allow. This step gives KV its own type: a ... - [Many buckets](https://elixirbyexample.com/core/kv-03-many-buckets.exs): One flat namespace gets crowded. Step 3 groups keys into named buckets (a map of maps) and adds a protocol so the store can be exported to a simple text form... ## Processes and OTP Concurrency the BEAM way: lightweight processes, messages, and supervision. - [Processes](https://elixirbyexample.com/otp/processes.exs): A BEAM process is not an OS process or thread. It's a tiny isolated unit (a few KB) with its own heap, scheduled by the VM. Spawning millions is normal. - [Sending and Receiving Messages](https://elixirbyexample.com/otp/messages.exs): Processes communicate only by sending messages. send/2 drops a message in the target's mailbox and returns immediately; it never blocks and never fails, even... - [Links and Monitors](https://elixirbyexample.com/otp/links-and-monitors.exs): Processes fail independently, but you usually need to know when one fails. Links and monitors are the two ways to find out. - [Task](https://elixirbyexample.com/otp/task.exs): Task runs a one-off computation in a process and gives you its result. It's the friendly face of spawn + monitor + receive. - [Agent](https://elixirbyexample.com/otp/agent.exs): An Agent is a process that only holds state. You pass it functions to read or change that state. It's a GenServer with the callbacks written for you. - [GenServer](https://elixirbyexample.com/otp/genserver.exs): A GenServer is a process that holds state and handles requests one at a time. You write the callbacks; OTP provides the receive loop, timeouts, error reporti... - [Supervisors](https://elixirbyexample.com/otp/supervisors.exs): A supervisor starts child processes, watches them, and restarts them when they crash. This is "let it crash" in practice: instead of defensive code for every... - [Registry](https://elixirbyexample.com/otp/registry.exs): Registered names (name: :foo) must be atoms, and atoms are never garbage collected. To name thousands of dynamic processes (one per user, room, bucket) use a... - [ETS](https://elixirbyexample.com/otp/ets.exs): ETS (Erlang Term Storage) is an in-memory table built into the VM. Any process can read it without sending a message, which makes it the standard tool for ho... ### Project: Make the store concurrent - [About this project](https://elixirbyexample.com/otp/kv.md): At the end of the Core chapter, KV is a good immutable data structure with a proper type, validation and many buckets. It also has a hard limit: a value only... - [The store becomes a process](https://elixirbyexample.com/otp/kv-04-a-store-process.exs): Steps 1-3 built a store that lives in a variable. To share it between processes it has to live in a process. A GenServer holds the buckets as its state, and ... - [Supervised buckets](https://elixirbyexample.com/otp/kv-05-supervised-buckets.exs): In step 4 one process served every bucket. Now each bucket is its own process: a crash in one bucket can't touch the others, and buckets work in parallel. Bu... - [Fast reads with ETS](https://elixirbyexample.com/otp/kv-06-fast-reads-with-ets.exs): Reads in step 5 went through a process mailbox, so a slow write delayed every reader. Most stores read far more than they write. Here, writes still go throug... - [Expiring keys](https://elixirbyexample.com/otp/kv-07-expiring-keys.exs): Step 6's keys never went away. A cache needs a TTL. Each row now stores an expiry time. Reads ignore expired rows right away, and a periodic sweep (a message... ## Distributed Elixir Many machines, one system: connected nodes, cluster-wide names and process groups. - [Nodes and Distribution](https://elixirbyexample.com/distributed/nodes.exs): A node is a running BEAM with a name. Named nodes can connect to each other and then send messages, spawn processes and call functions across machines as if ... - [Global Names with :global](https://elixirbyexample.com/distributed/global.exs): :global gives a process one name across the whole cluster. Every node agrees on who owns the name, so it suits singletons: one leader, one scheduler, one coo... - [Process Groups with :pg](https://elixirbyexample.com/distributed/pg.exs): :pg (process groups) lets any number of processes join a named group, on any node, and lets anyone look up the members. Where :global gives one process one n... ### Project: Spread the store across nodes - [About this project](https://elixirbyexample.com/distributed/kv.md): After the OTP chapter, KV is a solid single-node service: supervised buckets, fast reads from ETS, expiring keys. But every key still lives on one machine. W... - [Replicated buckets](https://elixirbyexample.com/distributed/kv-08-replicated-buckets.exs): Until now KV lived on one node: if that machine dies, so does every key. This step runs a replica of the store on every node. Replicas find each other throug...