feat: add source hyperlinks + remove thin from-source.md
Every source reference now links to elixir-lang/elixir at commit f4e1b34. 122 hyperlinks across 11 topic files. Added PATTERN_COMPLETE sentinels. Removed from-source.md (326 lines, shallow) — covered by existing files.
This commit is contained in:
+14
-12
@@ -6,7 +6,7 @@ Patterns extracted from Elixir's standard library source code.
|
||||
|
||||
## 1. List-Specialized Clause Before Protocol Dispatch
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 1723–1733
|
||||
**Source:** [lib/elixir/lib/enum.ex#L1723](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L1723)
|
||||
|
||||
**What it does:** Every public Enum function defines a `when is_list(enumerable)` clause first, then a generic fallback that uses the Enumerable protocol.
|
||||
|
||||
@@ -85,7 +85,7 @@ end
|
||||
|
||||
## 2. Build-Then-Reverse (Cons-Cell Accumulation)
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 1124, 1733, 2697
|
||||
**Source:** [lib/elixir/lib/enum.ex#L1124](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L1124), 1733, 2697
|
||||
|
||||
**What it does:** Accumulates results by prepending to a list (`[x | acc]`), then reverses at the end.
|
||||
|
||||
@@ -169,7 +169,7 @@ end
|
||||
|
||||
## 3. Pipeline for Linear Transformations, Bare Calls for Control Flow
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 1684–1685, 1551, vs 496–502
|
||||
**Source:** [lib/elixir/lib/enum.ex#L1684](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L1684), 1551, vs 496–502
|
||||
|
||||
**What it does:** Elixir core uses `|>` when data flows linearly through 2+ transformations. It does NOT use `|>` for single-step operations or when the first argument is computed by a `case`/`if`/`with`.
|
||||
|
||||
@@ -258,7 +258,7 @@ end
|
||||
|
||||
## 4. Pipeline Ending with `|> elem(1)` (Protocol Reduce Unwrap)
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 363, 403, 433, 468, 725, 1022, 2676
|
||||
**Source:** [lib/elixir/lib/enum.ex#L363](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L363), 403, 433, 468, 725, 1022, 2676
|
||||
|
||||
**What it does:** When calling `Enumerable.reduce/3` directly, the result is always `{:done | :halted | :suspended, acc}`. Core extracts the accumulator with `|> elem(1)`.
|
||||
|
||||
@@ -336,7 +336,7 @@ Enum.reduce([1, 2, 3], 0, &(&1 + &2)) |> elem(1)
|
||||
|
||||
## 5. Private Helper Decomposition: Recursive Workers with Guards
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 4975–4995, 5025–5039
|
||||
**Source:** [lib/elixir/lib/enum.ex#L4975](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L4975), 5025–5039
|
||||
|
||||
**What it does:** Complex operations are split into a public entry point (with validation guards) and a private recursive worker function. The worker uses pattern matching on structure (empty list, head|tail) and guards on counters.
|
||||
|
||||
@@ -435,7 +435,7 @@ def my_take(list, n), do: Enum.take(list, n)
|
||||
|
||||
## 6. Enum vs Stream Decision Pattern
|
||||
|
||||
**Source:** `lib/elixir/lib/stream.ex` lines 1–80 (module docs), `lib/elixir/lib/enum.ex`
|
||||
**Source:** [lib/elixir/lib/stream.ex#L1](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/stream.ex#L1) (module docs), `lib/elixir/lib/enum.ex`
|
||||
|
||||
**What it does:** Enum functions are eager (materialize intermediate lists). Stream functions are lazy (build computation recipes). Core uses Stream for:
|
||||
- Infinite sequences (`cycle`, `iterate`, `repeatedly`)
|
||||
@@ -528,7 +528,7 @@ config
|
||||
|
||||
## 7. Map.update vs Map.put Decision Pattern
|
||||
|
||||
**Source:** `lib/elixir/lib/map.ex` lines 670–700
|
||||
**Source:** [lib/elixir/lib/map.ex#L670](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/map.ex#L670)
|
||||
|
||||
**What it does:** `Map.update/4` transforms an existing value based on its current state. `Map.put/3` unconditionally sets a value regardless of current state.
|
||||
|
||||
@@ -603,7 +603,7 @@ Map.put(user, :name, new_name)
|
||||
|
||||
## 8. Pattern Matching on Map Structure for Dispatch
|
||||
|
||||
**Source:** `lib/elixir/lib/map.ex` lines 398, 509, 586
|
||||
**Source:** [lib/elixir/lib/map.ex#L398](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/map.ex#L398), 509, 586
|
||||
|
||||
**What it does:** Map functions use `case map do %{^key => value} -> ...` to dispatch on whether a key exists, rather than calling `has_key?` + conditional.
|
||||
|
||||
@@ -700,7 +700,7 @@ end
|
||||
|
||||
## 9. Delegating to Erlang BIFs with `defdelegate`
|
||||
|
||||
**Source:** `lib/elixir/lib/map.ex` lines 127, 143, 159, 173
|
||||
**Source:** [lib/elixir/lib/map.ex#L127](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/map.ex#L127), 143, 159, 173
|
||||
|
||||
**What it does:** When an Erlang function already does exactly what's needed, Elixir delegates directly rather than wrapping.
|
||||
|
||||
@@ -772,7 +772,7 @@ end
|
||||
|
||||
## 10. Reduce as the Universal Primitive
|
||||
|
||||
**Source:** `lib/elixir/lib/enum.ex` lines 19–21, 2660–2676
|
||||
**Source:** [lib/elixir/lib/enum.ex#L19](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/enum.ex#L19), 2660–2676
|
||||
|
||||
**What it does:** Nearly every Enum operation is built on top of `reduce`. The Enumerable protocol's core function is `reduce/3`. Everything else (`count`, `member?`, `slice`) is an optimization hint.
|
||||
|
||||
@@ -857,7 +857,7 @@ end
|
||||
|
||||
## 11. Keyword Multi-Clause Guard Dispatch (String.split pattern)
|
||||
|
||||
**Source:** `lib/elixir/lib/string.ex` lines 516–563
|
||||
**Source:** [lib/elixir/lib/string.ex#L516](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/string.ex#L516)
|
||||
|
||||
**What it does:** Functions with many input shapes use multiple `def` clauses with guards to dispatch, handling each case distinctly rather than using internal `cond`/`case`.
|
||||
|
||||
@@ -949,7 +949,7 @@ end
|
||||
|
||||
## 12. Lazy Private Helpers with `defp parts_to_index`
|
||||
|
||||
**Source:** `lib/elixir/lib/string.ex` lines 562–563
|
||||
**Source:** [lib/elixir/lib/string.ex#L562](https://github.com/elixir-lang/elixir/blob/f4e1b34617ef92052b65781f18eae5b88a490098/lib/elixir/lib/string.ex#L562)
|
||||
|
||||
**What it does:** Tiny private helpers that convert between API-level concepts and implementation-level values use single-line `defp` with guards.
|
||||
|
||||
@@ -1009,3 +1009,5 @@ def log(msg) when is_atom(msg), do: IO.puts(Atom.to_string(msg))
|
||||
```
|
||||
|
||||
**Why:** When a conversion is used exactly once and the calling function already dispatches on clauses, folding the conversion into the caller's clauses reduces indirection. Named helpers shine when reused or when they name a non-obvious transformation.
|
||||
|
||||
<!-- PATTERN_COMPLETE -->
|
||||
|
||||
Reference in New Issue
Block a user