<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Learn: Functional &amp; Parallel Thinking on tristancode</title><link>https://tristancode.com/learn/</link><description>Recent content in Learn: Functional &amp; Parallel Thinking on tristancode</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://tristancode.com/learn/index.xml" rel="self" type="application/rss+xml"/><item><title>Build Map and Filter</title><link>https://tristancode.com/learn/0014-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0014-puzzle/</guid><description>&lt;p&gt;You hand-built &lt;code&gt;transform&lt;/code&gt; (Lesson 9) and &lt;code&gt;keep&lt;/code&gt; (Lesson 10) using recursion. In this lesson you
formalise them as &lt;code&gt;my_map&lt;/code&gt; and &lt;code&gt;my_filter&lt;/code&gt;, and then try something harder: can filter be built from
map?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Map&lt;/strong&gt;: apply a function &lt;code&gt;f&lt;/code&gt; to every element of a list, producing a new list of the same length.
&lt;code&gt;map(f, [a, b, c])&lt;/code&gt; → &lt;code&gt;[f(a), f(b), f(c)]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter&lt;/strong&gt;: keep only the elements for which a predicate &lt;code&gt;pred&lt;/code&gt; returns &lt;code&gt;True&lt;/code&gt;.
&lt;code&gt;filter(pred, [a, b, c])&lt;/code&gt; → a sub-list of elements where &lt;code&gt;pred&lt;/code&gt; holds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predicate&lt;/strong&gt;: a function that takes a value and returns &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pure function&lt;/strong&gt;: output depends only on inputs; no side effects.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="part-1--my_map"&gt;Part 1 — &lt;code&gt;my_map&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Write &lt;code&gt;my_map(f, xs)&lt;/code&gt; recursively. No built-in &lt;code&gt;map&lt;/code&gt;, no list comprehensions.&lt;/p&gt;</description></item><item><title>Build the Fold</title><link>https://tristancode.com/learn/0015-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0015-puzzle/</guid><description>&lt;p&gt;&lt;code&gt;foldl&lt;/code&gt; (also called &lt;code&gt;reduce&lt;/code&gt; or &lt;code&gt;foldLeft&lt;/code&gt;) is the single most powerful list combinator. Every
list operation you have written — sum, length, reverse, map, filter — can be re-expressed as a
fold. This lesson builds it from scratch, and then puts it under stress.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fold (foldl)&lt;/strong&gt;: consumes a list by combining elements one-at-a-time with an accumulator. Takes
three arguments: a combining function &lt;code&gt;f&lt;/code&gt;, an initial accumulator value &lt;code&gt;init&lt;/code&gt;, and a list &lt;code&gt;xs&lt;/code&gt;.
Processes from left to right:
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;foldl(f, init, [a, b, c]) = f(f(f(init, a), b), c)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accumulator&lt;/strong&gt;: a value carried forward through each step, updated by the combining function.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Combining function&lt;/strong&gt;: &lt;code&gt;f(acc, x)&lt;/code&gt; takes the current accumulator and the current element,
returns the new accumulator.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="part-1--implement-foldl"&gt;Part 1 — Implement &lt;code&gt;foldl&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Write &lt;code&gt;foldl(f, init, xs)&lt;/code&gt; recursively. Base case: empty list → return &lt;code&gt;init&lt;/code&gt;. Recursive case:
apply &lt;code&gt;f&lt;/code&gt; to the accumulator and the head, recurse on the tail with the new accumulator.&lt;/p&gt;</description></item><item><title>Closures Capture Variables, Not Values</title><link>https://tristancode.com/learn/0016-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0016-puzzle/</guid><description>&lt;p&gt;A &lt;strong&gt;closure&lt;/strong&gt; is a function that &lt;em&gt;captures&lt;/em&gt; variables from the scope where it was defined — not
just their values at the moment of creation, but the &lt;em&gt;variables themselves&lt;/em&gt;. When the function is
called later, it reads the variable as it exists at call time, not at definition time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scope&lt;/strong&gt;: the region of code where a name is visible. In Python, a function body has its own
local scope; the enclosing function&amp;rsquo;s variables are in the &lt;em&gt;enclosing scope&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Closure&lt;/strong&gt;: a function bundled with the environment (set of captured variables) from its defining
scope. The function &amp;ldquo;closes over&amp;rdquo; those variables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Late binding&lt;/strong&gt;: the value of a captured variable is looked up &lt;em&gt;when the function is called&lt;/em&gt;, not
when it is defined.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Consider this code:&lt;/p&gt;</description></item><item><title>Count the List</title><link>https://tristancode.com/learn/0005-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0005-puzzle/</guid><description>&lt;p&gt;Count how many elements are in a list — recursively, no &lt;code&gt;len&lt;/code&gt;, no loop.&lt;/p&gt;
&lt;p&gt;Recap so it stands alone. &lt;strong&gt;Recursion&lt;/strong&gt; = a function that calls itself on a smaller piece, with a
&lt;strong&gt;base case&lt;/strong&gt; (smallest input, answered directly, stops the recursion) and a &lt;strong&gt;recursive case&lt;/strong&gt; (call
yourself on something smaller, then use the result). A list is &lt;strong&gt;a first element &lt;code&gt;xs[0]&lt;/code&gt; followed by
the rest &lt;code&gt;xs[1:]&lt;/code&gt;&lt;/strong&gt;; the empty list is written &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Curry, Partial, Compose</title><link>https://tristancode.com/learn/0017-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0017-puzzle/</guid><description>&lt;p&gt;Three tools. Each is a single concept; together they form the vocabulary of functional plumbing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Currying&lt;/strong&gt;: converting a function that takes multiple arguments into a chain of functions that
each take one argument. &lt;code&gt;f(a, b)&lt;/code&gt; becomes &lt;code&gt;curried_f(a)(b)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partial application&lt;/strong&gt;: fixing some of a function&amp;rsquo;s arguments in advance, returning a function
that takes the remaining arguments. &lt;code&gt;add(3, _)&lt;/code&gt; fixed at &lt;code&gt;3&lt;/code&gt; becomes a &amp;ldquo;add 3 to anything&amp;rdquo; function.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Function composition&lt;/strong&gt;: combining two functions into one. &lt;code&gt;compose(f, g)(x) = f(g(x))&lt;/code&gt; — &lt;code&gt;g&lt;/code&gt;
runs first, &lt;code&gt;f&lt;/code&gt; runs second.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Closure&lt;/strong&gt; (from Lesson 16): a function that captures variables from its defining scope.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="part-1--curry-add-by-hand"&gt;Part 1 — Curry &lt;code&gt;add&lt;/code&gt; by hand&lt;/h3&gt;
&lt;p&gt;The two-argument &lt;code&gt;add&lt;/code&gt; below takes both arguments at once. Write a curried version &lt;code&gt;add_c&lt;/code&gt; that
takes one argument and returns a function that takes the second.&lt;/p&gt;</description></item><item><title>Find It, Then Transform It</title><link>https://tristancode.com/learn/0009-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0009-puzzle/</guid><description>&lt;p&gt;Two exercises. Both use pure recursion — no built-in &lt;code&gt;in&lt;/code&gt;, no &lt;code&gt;map&lt;/code&gt;, no list comprehensions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recursion recap&lt;/strong&gt; (standing alone): a function is recursive when it calls itself on a smaller
version of its input. The base case handles the smallest possible input directly; the recursive case
breaks the input down one step and uses the result of the smaller call. For lists, the base case is
usually the empty list &lt;code&gt;[]&lt;/code&gt;, and the recursive case peels off the first element &lt;code&gt;xs[0]&lt;/code&gt; and
recurses on the rest &lt;code&gt;xs[1:]&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Find the Last Element</title><link>https://tristancode.com/learn/0004-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0004-puzzle/</guid><description>&lt;p&gt;Get the &lt;strong&gt;last&lt;/strong&gt; element of a list, recursively — no loops, no indexing tricks like &lt;code&gt;xs[-1]&lt;/code&gt;. Just a
function that calls itself.&lt;/p&gt;
&lt;p&gt;Quick recap of the tool, so this stands alone. &lt;strong&gt;Recursion&lt;/strong&gt; means solving a problem by calling a
function on a smaller piece of itself. Every recursive function needs a &lt;strong&gt;base case&lt;/strong&gt; (the smallest
input, answered outright, which stops the recursion) and a &lt;strong&gt;recursive case&lt;/strong&gt; (call yourself on
something smaller, then use the result). We&amp;rsquo;ll treat a list as &lt;strong&gt;a first element &lt;code&gt;xs[0]&lt;/code&gt; followed by
the rest &lt;code&gt;xs[1:]&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Flatten the Nesting</title><link>https://tristancode.com/learn/0011-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0011-puzzle/</guid><description>&lt;p&gt;Every recursion you&amp;rsquo;ve written so far has had this shape: peel the head, do something with it, then
recurse &lt;em&gt;only on the tail&lt;/em&gt;. This puzzle breaks that pattern.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flatten&lt;/strong&gt; a nested list: given a list that may contain elements or other lists (nested to any
depth), produce a single flat list of all the leaf elements in order.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flatten([&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, [&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;], [&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;]], &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;# [1, 2, 3, 4, 5, 6, 7]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flatten([[[[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]]]]) &lt;span style="color:#75715e"&gt;# [1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flatten([]) &lt;span style="color:#75715e"&gt;# []&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flatten([&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;# [1, 2, 3] (already flat — works too)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Recursion recap (standalone):&lt;/strong&gt; a recursive function calls itself on a smaller input until it
reaches a base case answered directly. A list is either empty &lt;code&gt;[]&lt;/code&gt; or has a first element &lt;code&gt;xs[0]&lt;/code&gt;
and a rest &lt;code&gt;xs[1:]&lt;/code&gt;. In Python, &lt;code&gt;isinstance(x, list)&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt; when &lt;code&gt;x&lt;/code&gt; is a list.&lt;/p&gt;</description></item><item><title>Functions Are Values</title><link>https://tristancode.com/learn/0013-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0013-puzzle/</guid><description>&lt;p&gt;In most languages a function is just a value — you can assign it to a variable, put it in a list,
pass it to another function, and return it from a function. These are called &lt;strong&gt;higher-order
functions&lt;/strong&gt; (HOFs): functions that operate on other functions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;First-class function&lt;/strong&gt;: a function that can be stored, passed, and returned like any other value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Higher-order function&lt;/strong&gt;: a function that takes a function as an argument or returns one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;compose(f, g)(x)&lt;/code&gt;&lt;/strong&gt; returns &lt;code&gt;f(g(x))&lt;/code&gt; — &lt;code&gt;g&lt;/code&gt; runs first, &lt;code&gt;f&lt;/code&gt; runs second.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Read this code carefully and trace it by hand:&lt;/p&gt;</description></item><item><title>Keep, Drop, and Slice</title><link>https://tristancode.com/learn/0010-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0010-puzzle/</guid><description>&lt;p&gt;Four functions. No loops, no &lt;code&gt;filter&lt;/code&gt;, no slicing, no built-ins except comparison. All return new
lists; the original is never mutated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recursion recap (standalone):&lt;/strong&gt; a recursive function calls itself on a smaller input. For lists
the base case is the empty list &lt;code&gt;[]&lt;/code&gt;; the recursive case peels off the first element &lt;code&gt;xs[0]&lt;/code&gt; and
recurses on the rest &lt;code&gt;xs[1:]&lt;/code&gt;. A &lt;strong&gt;predicate&lt;/strong&gt; is a function that takes a value and returns a
boolean (&lt;code&gt;True&lt;/code&gt;/&lt;code&gt;False&lt;/code&gt;).&lt;/p&gt;</description></item><item><title>Push the Effects to the Edge</title><link>https://tristancode.com/learn/0008-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0008-puzzle/</guid><description>&lt;p&gt;&lt;strong&gt;Side effects&lt;/strong&gt; — printing, reading input, writing files, talking to a database — are unavoidable.
Real programs must do them. The question isn&amp;rsquo;t whether to have them; it&amp;rsquo;s &lt;em&gt;where&lt;/em&gt; to put them.&lt;/p&gt;
&lt;p&gt;Recap of terms used here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;pure function&lt;/strong&gt; produces an output that depends only on its inputs and has no side effects.
It can be called any number of times, in any order, without changing the world.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Referential transparency&lt;/strong&gt; (Lesson 7): a pure call can always be replaced by its result.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Side effect&lt;/strong&gt;: anything a function does &lt;em&gt;besides&lt;/em&gt; returning a value — printing, mutating global
state, making network requests, generating random numbers, reading the clock, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The functional strategy is &lt;strong&gt;&amp;ldquo;effects at the edges&amp;rdquo;&lt;/strong&gt;: write a pure &lt;em&gt;core&lt;/em&gt; that does all the
interesting computation, wrap it with a thin &lt;em&gt;shell&lt;/em&gt; that handles I/O. The core stays fully
testable, reusable, and safe to parallelize. The shell knows how to talk to the outside world.&lt;/p&gt;</description></item><item><title>Reduce Reconstructs Everything</title><link>https://tristancode.com/learn/0018-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0018-puzzle/</guid><description>&lt;p&gt;This is the payoff for Stage 2. You will re-derive every list operation you&amp;rsquo;ve written — using
&lt;em&gt;only&lt;/em&gt; &lt;code&gt;foldl&lt;/code&gt; as the engine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;foldl&lt;/code&gt; recap (standalone):&lt;/strong&gt; consumes a list by updating an accumulator left-to-right.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foldl&lt;/span&gt;(f, init, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; init
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; foldl(f, f(init, xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]), xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;foldl(f, init, [a, b, c])&lt;/code&gt; expands to &lt;code&gt;f(f(f(init, a), b), c)&lt;/code&gt;. The combining function &lt;code&gt;f&lt;/code&gt; takes
&lt;code&gt;(acc, element)&lt;/code&gt; and returns the new accumulator. The &lt;code&gt;init&lt;/code&gt; is the starting accumulator.&lt;/p&gt;</description></item><item><title>Reverse a List — Twice</title><link>https://tristancode.com/learn/0006-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0006-puzzle/</guid><description>&lt;p&gt;Reverse a list recursively: &lt;code&gt;reverse([1, 2, 3])&lt;/code&gt; should give &lt;code&gt;[3, 2, 1]&lt;/code&gt;. No loops, no built-in
&lt;code&gt;reversed&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Standing on its own: &lt;strong&gt;recursion&lt;/strong&gt; is a function that calls itself on a smaller piece, with a &lt;strong&gt;base
case&lt;/strong&gt; (smallest input, answered directly) and a &lt;strong&gt;recursive case&lt;/strong&gt; (call yourself on something
smaller, then combine). A list is &lt;strong&gt;a first element &lt;code&gt;xs[0]&lt;/code&gt; followed by the rest &lt;code&gt;xs[1:]&lt;/code&gt;&lt;/strong&gt;. In Python
pseudocode, &lt;code&gt;a + b&lt;/code&gt; on two lists &lt;strong&gt;concatenates&lt;/strong&gt; them into a new list: &lt;code&gt;[1] + [2, 3]&lt;/code&gt; is &lt;code&gt;[1, 2, 3]&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Solution: Build Map and Filter</title><link>https://tristancode.com/learn/0014-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0014-solution/</guid><description>&lt;h3 id="part-1--my_map"&gt;Part 1 — &lt;code&gt;my_map&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_map&lt;/span&gt;(f, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [f(xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; my_map(f, xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Identical to &lt;code&gt;transform&lt;/code&gt; from Lesson 9 — you already built this. &lt;code&gt;map&lt;/code&gt; is just the canonical name.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-2--my_filter"&gt;Part 2 — &lt;code&gt;my_filter&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_filter&lt;/span&gt;(pred, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; pred(xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; my_filter(pred, xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; my_filter(pred, xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Same as &lt;code&gt;keep&lt;/code&gt; from Lesson 10.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-3--why-filter-cannot-be-written-in-terms-of-map-alone"&gt;Part 3 — Why filter cannot be written in terms of map alone&lt;/h3&gt;
&lt;p&gt;You cannot implement &lt;code&gt;my_filter&lt;/code&gt; using only &lt;code&gt;my_map&lt;/code&gt;. Here&amp;rsquo;s why:&lt;/p&gt;</description></item><item><title>Solution: Build the Fold</title><link>https://tristancode.com/learn/0015-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0015-solution/</guid><description>&lt;h3 id="part-1--foldl"&gt;Part 1 — &lt;code&gt;foldl&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foldl&lt;/span&gt;(f, init, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; init
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; foldl(f, f(init, xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]), xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each recursive call passes the updated accumulator &lt;code&gt;f(init, xs[0])&lt;/code&gt; as the new &lt;code&gt;init&lt;/code&gt;. The
recursive call is in tail position — this is already tail-recursive and runs in constant stack
space in a TCO-capable runtime.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-2--trace"&gt;Part 2 — Trace&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;foldl(lambda acc, x: acc - x, 100, [10, 20, 5])&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;foldl(sub, 100, [10, 20, 5])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = foldl(sub, 100-10, [20, 5]) = foldl(sub, 90, [20, 5])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = foldl(sub, 90-20, [5]) = foldl(sub, 70, [5])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = foldl(sub, 70-5, []) = foldl(sub, 65, [])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = 65
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Equivalent to &lt;code&gt;((100 - 10) - 20) - 5 = 65&lt;/code&gt;. Left-associative — parentheses nest to the left.&lt;/p&gt;</description></item><item><title>Solution: Closures Capture Variables, Not Values</title><link>https://tristancode.com/learn/0016-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0016-solution/</guid><description>&lt;p&gt;&lt;strong&gt;The answer is &lt;code&gt;[12, 12, 12]&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="why"&gt;Why&lt;/h3&gt;
&lt;p&gt;After &lt;code&gt;for i in range(3)&lt;/code&gt; the loop variable &lt;code&gt;i&lt;/code&gt; holds &lt;code&gt;2&lt;/code&gt; — the last value it was assigned.
All three lambdas close over the &lt;em&gt;same&lt;/em&gt; variable &lt;code&gt;i&lt;/code&gt; (not a copy of its value at creation time).
When you call them, they all read &lt;code&gt;i = 2&lt;/code&gt; and return &lt;code&gt;10 + 2 = 12&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fns &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;): &lt;span style="color:#75715e"&gt;# i = 0, then 1, then 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fns&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(&lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; x: x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; i) &lt;span style="color:#75715e"&gt;# captures the VARIABLE i, not its current value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# after the loop: i == 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;results &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [f(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; f &lt;span style="color:#f92672"&gt;in&lt;/span&gt; fns]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# each f(10) reads i at call time → i==2 → 10+2 = 12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# results = [12, 12, 12]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This surprises many developers who expect &lt;code&gt;[10, 11, 12]&lt;/code&gt; — they imagine the lambda &amp;ldquo;froze&amp;rdquo; &lt;code&gt;i&lt;/code&gt;&amp;rsquo;s
value at creation time. It doesn&amp;rsquo;t. Closures in Python (and most languages) capture the binding —
the variable itself — not a snapshot of its value.&lt;/p&gt;</description></item><item><title>Solution: Count the List</title><link>https://tristancode.com/learn/0005-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0005-solution/</guid><description>&lt;p&gt;&lt;strong&gt;B is the correct recursive length:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;(xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; [] &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; length(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Empty list → &lt;code&gt;0&lt;/code&gt;. Otherwise, count the first element as &lt;code&gt;1&lt;/code&gt; and add the length of the rest. For
&lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;length([&amp;#34;a&amp;#34;,&amp;#34;b&amp;#34;,&amp;#34;c&amp;#34;]) = 1 + length([&amp;#34;b&amp;#34;,&amp;#34;c&amp;#34;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = 1 + (1 + length([&amp;#34;c&amp;#34;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = 1 + (1 + (1 + length([])))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = 1 + (1 + (1 + 0)) = 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The bugs in the others:&lt;/p&gt;</description></item><item><title>Solution: Curry, Partial, Compose</title><link>https://tristancode.com/learn/0017-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0017-solution/</guid><description>&lt;h3 id="part-1--currying-add"&gt;Part 1 — Currying &lt;code&gt;add&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_c&lt;/span&gt;(x):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;inner&lt;/span&gt;(y):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; inner
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# or, more compactly:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add_c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; x: &lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; y: x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add_c(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add10 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; add_c(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add10(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add10(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 110&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;add_c(10)&lt;/code&gt; returns the &lt;code&gt;inner&lt;/code&gt; closure with &lt;code&gt;x=10&lt;/code&gt; captured. Every subsequent call just adds 10.
This is &lt;code&gt;make_adder(10)&lt;/code&gt; from Lesson 13 — currying is the general pattern behind all those factories.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-2--functoolspartial"&gt;Part 2 — &lt;code&gt;functools.partial&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; functools &lt;span style="color:#f92672"&gt;import&lt;/span&gt; partial
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;square &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partial(power, exponent&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# or: partial(power, 2) for positional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cube &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partial(power, exponent&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;powers_of_2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partial(power, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;square(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cube(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;powers_of_2(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 256&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: &lt;code&gt;partial(power, 2)&lt;/code&gt; fixes the &lt;em&gt;first&lt;/em&gt; positional argument (&lt;code&gt;base=2&lt;/code&gt;). &lt;code&gt;partial(power, exponent=2)&lt;/code&gt;
uses a keyword argument to fix the &lt;em&gt;second&lt;/em&gt;. Both work; keyword form is clearer for non-first args.&lt;/p&gt;</description></item><item><title>Solution: Find It, Then Transform It</title><link>https://tristancode.com/learn/0009-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0009-solution/</guid><description>&lt;h3 id="part-1--contains"&gt;Part 1 — &lt;code&gt;contains&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;contains&lt;/span&gt;(xs, target):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; target:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; contains(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], target)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Three branches: empty list → definitely not there; head matches → found it; otherwise → the answer
is the same as whether &lt;code&gt;target&lt;/code&gt; is in the rest. Trace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;contains([3,7,1], 7)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = contains([7,1], 7) # 3 ≠ 7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = True # 7 == 7 ✓
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Short-circuits as soon as it finds a match — it doesn&amp;rsquo;t scan the rest of the list.&lt;/p&gt;</description></item><item><title>Solution: Find the Last Element</title><link>https://tristancode.com/learn/0004-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0004-solution/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;last&lt;/span&gt;(xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(xs) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#75715e"&gt;# base case: the only element IS the last&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; last(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:]) &lt;span style="color:#75715e"&gt;# recursive case: last of the rest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Base case:&lt;/strong&gt; a one-element list &lt;code&gt;[x]&lt;/code&gt; — its last element is &lt;code&gt;xs[0]&lt;/code&gt;, the element itself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recursive case:&lt;/strong&gt; the last element of &lt;code&gt;[3, 1, 2]&lt;/code&gt; is exactly the last element of &lt;code&gt;[1, 2]&lt;/code&gt;, which is
the last element of &lt;code&gt;[2]&lt;/code&gt;. Each step throws away the first element and asks the same question of a
shorter list. Notice the difference from &lt;a href="../0003-puzzle/"&gt;summing a list&lt;/a&gt;: there we &lt;em&gt;combined&lt;/em&gt;
&lt;code&gt;xs[0]&lt;/code&gt; with the recursive result (&lt;code&gt;xs[0] + total(xs[1:])&lt;/code&gt;); here we &lt;em&gt;discard&lt;/em&gt; &lt;code&gt;xs[0]&lt;/code&gt; and just pass
the answer straight up (&lt;code&gt;last(xs[1:])&lt;/code&gt;). The first element does no work — it&amp;rsquo;s only along for the
ride until we reach the last one.&lt;/p&gt;</description></item><item><title>Solution: Flatten the Nesting</title><link>https://tristancode.com/learn/0011-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0011-solution/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flatten&lt;/span&gt;(xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; isinstance(xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;], list):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; flatten(xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; flatten(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; flatten(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Trace &lt;code&gt;flatten([1, [2, 3], 4])&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flatten([1, [2,3], 4])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = [1] + flatten([[2,3], 4]) # head is 1 (leaf)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = [1] + (flatten([2,3]) + flatten([4])) # head is [2,3] (list)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = [1] + ([2,3] + [4]) # flatten([2,3]) = [2]+flatten([3])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = [1, 2, 3, 4] # = [2]+[3]==[2,3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two recursive calls: &lt;code&gt;flatten(xs[0])&lt;/code&gt; drills &lt;em&gt;into&lt;/em&gt; the head, &lt;code&gt;flatten(xs[1:])&lt;/code&gt; advances &lt;em&gt;along&lt;/em&gt;
the rest. That&amp;rsquo;s the new pattern — recursive on both dimensions at once.&lt;/p&gt;</description></item><item><title>Solution: Functions Are Values</title><link>https://tristancode.com/learn/0013-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0013-solution/</guid><description>&lt;p&gt;&lt;strong&gt;The answer is 42.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="trace"&gt;Trace&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add5 ≡ λx. x + 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;double ≡ λx. x * 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;triple ≡ λx. x * 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;steps = [add5, double, triple]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The loop composes step-by-step:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;before loop: pipeline = add5 # x → x+5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iteration 1: step = double
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pipeline = compose(double, add5)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; # pipeline(x) = double(add5(x)) = 2*(x+5)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iteration 2: step = triple
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pipeline = compose(triple, compose(double, add5))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; # pipeline(x) = triple(double(add5(x))) = 3 * 2 * (x+5) = 6*(x+5)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So &lt;code&gt;pipeline(2) = 6 * (2+5) = 6 * 7 = 42&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Solution: Keep, Drop, and Slice</title><link>https://tristancode.com/learn/0010-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0010-solution/</guid><description>&lt;h3 id="part-1--keep"&gt;Part 1 — &lt;code&gt;keep&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;keep&lt;/span&gt;(xs, pred):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; pred(xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; keep(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], pred)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; keep(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], pred)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When the head passes the predicate, include it; otherwise discard it and recurse. Notice that
&lt;code&gt;keep(xs[1:], pred)&lt;/code&gt; appears in both branches — the only difference is whether &lt;code&gt;xs[0]&lt;/code&gt; is prepended.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-2--take"&gt;Part 2 — &lt;code&gt;take&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;take&lt;/span&gt;(n, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;or&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; take(n &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two base cases joined by &lt;code&gt;or&lt;/code&gt;: we stop when we&amp;rsquo;ve taken enough &lt;em&gt;or&lt;/em&gt; when the list runs out. Both
matter — one guards the count, the other guards the list. Miss either and you get an infinite loop
or an index error.&lt;/p&gt;</description></item><item><title>Solution: Push the Effects to the Edge</title><link>https://tristancode.com/learn/0008-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0008-solution/</guid><description>&lt;h3 id="the-split"&gt;The split&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;compute&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, n &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; i &lt;span style="color:#f92672"&gt;*&lt;/span&gt; i
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;-=&lt;/span&gt; i
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; total
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; int(input(&lt;span style="color:#e6db74"&gt;&amp;#34;Enter a positive integer: &amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; compute(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Result for &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;n&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;result&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;compute(4)&lt;/code&gt; → &lt;code&gt;2² + 4² − 1 − 3 = 4 + 16 − 1 − 3 = 16&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;compute&lt;/code&gt; is pure: same input, same output, always, no matter how many times you call it. &lt;code&gt;run&lt;/code&gt; is
the only place that touches I/O.&lt;/p&gt;</description></item><item><title>Solution: Reduce Reconstructs Everything</title><link>https://tristancode.com/learn/0018-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0018-solution/</guid><description>&lt;h3 id="part-1--my_sum-and-my_product"&gt;Part 1 — &lt;code&gt;my_sum&lt;/code&gt; and &lt;code&gt;my_product&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;my_sum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; xs: foldl(&lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; acc, x: acc &lt;span style="color:#f92672"&gt;+&lt;/span&gt; x, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, xs)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;my_product &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; xs: foldl(&lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; acc, x: acc &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, xs)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;init=0&lt;/code&gt; for sum: adding nothing to an empty list gives 0 (the additive identity).
&lt;code&gt;init=1&lt;/code&gt; for product: the multiplicative identity — multiplying nothing gives 1. Use &lt;code&gt;0&lt;/code&gt; and
&lt;code&gt;my_product([]) = 0&lt;/code&gt; instead of 1, which would be wrong.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="part-2--my_map_via_fold"&gt;Part 2 — &lt;code&gt;my_map_via_fold&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_map_via_fold&lt;/span&gt;(f, xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; foldl(&lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; acc, x: acc &lt;span style="color:#f92672"&gt;+&lt;/span&gt; [f(x)], [], xs)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;init=[]&lt;/code&gt; (empty output). At each step, apply &lt;code&gt;f&lt;/code&gt; to the element and append it to the right
of the accumulator. The list grows in order — first to last — because foldl processes left-to-right
and we append to the right.&lt;/p&gt;</description></item><item><title>Solution: Reverse a List — Twice</title><link>https://tristancode.com/learn/0006-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0006-solution/</guid><description>&lt;h3 id="part-1--the-obvious-version"&gt;Part 1 — the obvious version&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reverse&lt;/span&gt;(xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# reverse of nothing is nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; reverse(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:]) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; [xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The idea: reverse &lt;em&gt;the rest&lt;/em&gt; of the list, then stick the first element on the &lt;strong&gt;end&lt;/strong&gt; — because in the
reversed result, the original first element must come last. Trace it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reverse([1,2,3]) = reverse([2,3]) + [1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = (reverse([3]) + [2]) + [1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = ((reverse([]) + [3]) + [2]) + [1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = (([] + [3]) + [2]) + [1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = [3,2,1]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Correct — and pure: a new list out, the original untouched.&lt;/p&gt;</description></item><item><title>Solution: Spot the Pure Function</title><link>https://tristancode.com/learn/0001-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0001-solution/</guid><description>&lt;p&gt;&lt;strong&gt;The pure one is A, &lt;code&gt;add_tax&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run it with &lt;code&gt;add_tax(100)&lt;/code&gt; and you get &lt;code&gt;108.0&lt;/code&gt; — today, tomorrow, on any machine, no matter what else
the program is doing. It reads its input (&lt;code&gt;price&lt;/code&gt;), reads a constant (&lt;code&gt;TAX&lt;/code&gt;), and returns a value. It
touches nothing else and changes nothing else. That&amp;rsquo;s purity.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s why each of the others fails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;B — &lt;code&gt;add_to_cart&lt;/code&gt; has a side effect.&lt;/strong&gt; &lt;code&gt;cart.append(item)&lt;/code&gt; mutates a list that lives &lt;em&gt;outside&lt;/em&gt; the
function. Call it twice with the same &lt;code&gt;item&lt;/code&gt; and the world is different each time — the cart keeps
growing. The return value also depends on history, not just the argument.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C — &lt;code&gt;now_plus&lt;/code&gt; depends on more than its inputs.&lt;/strong&gt; &lt;code&gt;time.time()&lt;/code&gt; returns the current clock, so
&lt;code&gt;now_plus(10)&lt;/code&gt; gives a different answer every time you call it. Same input, different output → impure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;D — &lt;code&gt;greet&lt;/code&gt; has a side effect and returns nothing.&lt;/strong&gt; &lt;code&gt;print&lt;/code&gt; pushes text to the screen (the
outside world). Its &amp;ldquo;result&amp;rdquo; is the act of printing, not a returned value.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="why-this-is-the-foundation"&gt;Why this is the foundation&lt;/h3&gt;
&lt;p&gt;Pure functions buy you three things that this whole path keeps cashing in:&lt;/p&gt;</description></item><item><title>Solution: Sum a List Without a Loop</title><link>https://tristancode.com/learn/0003-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0003-solution/</guid><description>&lt;p&gt;Here&amp;rsquo;s the function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;total&lt;/span&gt;(xs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; xs &lt;span style="color:#f92672"&gt;==&lt;/span&gt; []:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#75715e"&gt;# base case&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; total(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:]) &lt;span style="color:#75715e"&gt;# recursive case&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;The empty list sums to &lt;code&gt;0&lt;/code&gt;.&lt;/strong&gt; That&amp;rsquo;s the right base case for two reasons: it&amp;rsquo;s the true answer (an
empty list has nothing to add), and &lt;code&gt;0&lt;/code&gt; is the value that doesn&amp;rsquo;t disturb a sum — adding it changes
nothing. Every recursion needs a base case like this, or it would call itself forever.&lt;/p&gt;</description></item><item><title>Solution: Tail Calls and the Accumulator Pattern</title><link>https://tristancode.com/learn/0012-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0012-solution/</guid><description>&lt;h3 id="part-1--answers"&gt;Part 1 — Answers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A — &lt;code&gt;sum_list&lt;/code&gt;: NOT a tail call.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; sum_list(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After &lt;code&gt;sum_list(xs[1:])&lt;/code&gt; returns, you still have to add &lt;code&gt;xs[0]&lt;/code&gt; to it. The &lt;code&gt;+&lt;/code&gt; is pending
work. The call is wrapped inside another operation — not in tail position.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B — &lt;code&gt;sum_tail&lt;/code&gt;: IS a tail call.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; sum_tail(xs[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], acc &lt;span style="color:#f92672"&gt;+&lt;/span&gt; xs[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result of the recursive call is returned &lt;em&gt;directly&lt;/em&gt; — no further operation. &lt;code&gt;acc + xs[0]&lt;/code&gt;
is computed &lt;em&gt;before&lt;/em&gt; the call, as the new argument. After the call completes, the caller just
hands back what it received. That&amp;rsquo;s tail position.&lt;/p&gt;</description></item><item><title>Solution: The List That Wouldn't Change</title><link>https://tristancode.com/learn/0002-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0002-solution/</guid><description>&lt;p&gt;&lt;strong&gt;The answer is B: &lt;code&gt;return xs + [4]&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xs + [4]&lt;/code&gt; evaluates to a &lt;em&gt;new&lt;/em&gt; list. The original &lt;code&gt;xs&lt;/code&gt; is read but never touched, so the caller&amp;rsquo;s
&lt;code&gt;scores&lt;/code&gt; stays &lt;code&gt;[10, 20, 30]&lt;/code&gt; and &lt;code&gt;result&lt;/code&gt; becomes &lt;code&gt;[10, 20, 30, 4]&lt;/code&gt;. Two separate values, exactly as
the caller expected.&lt;/p&gt;
&lt;p&gt;The other three all mutate the original in place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A — &lt;code&gt;xs.append(4)&lt;/code&gt;&lt;/strong&gt; tacks &lt;code&gt;4&lt;/code&gt; onto the very list the caller passed in. &lt;code&gt;scores&lt;/code&gt; becomes
&lt;code&gt;[10, 20, 30, 4]&lt;/code&gt; too. Surprise side effect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;D — &lt;code&gt;xs += [4]&lt;/code&gt;&lt;/strong&gt; looks like &amp;ldquo;make a new list,&amp;rdquo; but for a Python list &lt;code&gt;+=&lt;/code&gt; is in-place extension —
the same object the caller holds is modified.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C — &lt;code&gt;xs[len(xs):] = [4]&lt;/code&gt;&lt;/strong&gt; is slice assignment, another in-place edit of the original.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The trap in B-vs-D is worth remembering: &lt;code&gt;xs = xs + [4]&lt;/code&gt; rebinds a name to a new list, but
&lt;code&gt;xs += [4]&lt;/code&gt; mutates the existing one. They look almost identical and behave oppositely.&lt;/p&gt;</description></item><item><title>Solution: The Substitution Game</title><link>https://tristancode.com/learn/0007-solution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0007-solution/</guid><description>&lt;p&gt;&lt;strong&gt;D is the only referentially transparent option.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;(x): &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;f(5)&lt;/code&gt; is always &lt;code&gt;10&lt;/code&gt;, period. You can swap every &lt;code&gt;f(5)&lt;/code&gt; in your code for &lt;code&gt;10&lt;/code&gt; and the program
behaves identically. Nothing else changes — no side channel is disturbed, no hidden state updates,
no output appears on the terminal.&lt;/p&gt;
&lt;h3 id="why-a-b-and-c-break-the-substitution"&gt;Why A, B, and C break the substitution&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A — hidden output:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;(x):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(x)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The return value is &lt;code&gt;10&lt;/code&gt;, but printing &lt;code&gt;5&lt;/code&gt; to the terminal is a side effect. A program with two
calls to &lt;code&gt;f(5)&lt;/code&gt; prints &lt;code&gt;5&lt;/code&gt; twice. Replace those calls with &lt;code&gt;10&lt;/code&gt; and nothing is printed at all.
The two programs are observable differently — the substitution changed behaviour.&lt;/p&gt;</description></item><item><title>Spot the Pure Function</title><link>https://tristancode.com/learn/0001-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0001-puzzle/</guid><description>&lt;p&gt;Almost everything in this path rests on one idea, so we start there: the &lt;strong&gt;pure function&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A function is &lt;strong&gt;pure&lt;/strong&gt; when both of these hold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Its output depends only on its inputs.&lt;/strong&gt; Same arguments in → same answer out, every single time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It has no side effects.&lt;/strong&gt; It doesn&amp;rsquo;t change anything outside itself — no writing to a global, a
file, a database, or the screen; and it doesn&amp;rsquo;t modify the arguments it was handed. It just takes
values and returns a value.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A function that breaks either rule is called &lt;strong&gt;impure&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Sum a List Without a Loop</title><link>https://tristancode.com/learn/0003-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0003-puzzle/</guid><description>&lt;p&gt;Here&amp;rsquo;s a challenge with a rule: &lt;strong&gt;add up all the numbers in a list, but you may not use a loop&lt;/strong&gt; (no
&lt;code&gt;for&lt;/code&gt;, no &lt;code&gt;while&lt;/code&gt;) and no built-in &lt;code&gt;sum&lt;/code&gt;. Your only tool is the function calling &lt;em&gt;itself&lt;/em&gt;. That tool is
&lt;strong&gt;recursion&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;recursive function&lt;/strong&gt; is one that solves a problem by calling itself on a smaller piece of the same
problem. Every recursive function needs two parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;base case&lt;/strong&gt; — the smallest input, simple enough to answer outright with no further calls. It&amp;rsquo;s
what stops the recursion.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;recursive case&lt;/strong&gt; — solve a &lt;em&gt;smaller&lt;/em&gt; version of the problem by calling yourself, then combine
that result with the current piece.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Think about a list as &lt;strong&gt;a first element followed by the rest of the list&lt;/strong&gt;. For example
&lt;code&gt;[3, 1, 2]&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt; followed by &lt;code&gt;[1, 2]&lt;/code&gt;. We&amp;rsquo;ll write the answer in Python-flavored pseudocode, where
&lt;code&gt;xs[0]&lt;/code&gt; is the first element and &lt;code&gt;xs[1:]&lt;/code&gt; is &amp;ldquo;everything after the first&amp;rdquo;:&lt;/p&gt;</description></item><item><title>Tail Calls and the Accumulator Pattern</title><link>https://tristancode.com/learn/0012-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0012-puzzle/</guid><description>&lt;p&gt;You&amp;rsquo;ve used accumulators in Lessons 5 and 6 to make counting and reversing O(n). This lesson
makes the underlying principle explicit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terms used here (standalone):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tail call&lt;/strong&gt;: a call where the &lt;em&gt;return value of the recursive call&lt;/em&gt; is immediately returned —
nothing is left to do with the result once it comes back. Formally, the call is in &lt;em&gt;tail
position&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-tail call&lt;/strong&gt;: a call where there&amp;rsquo;s still work to do with the result before returning (like
adding &lt;code&gt;1 +&lt;/code&gt; to it, or prepending &lt;code&gt;[x] +&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tail-recursive function&lt;/strong&gt;: one whose recursive calls are all tail calls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCO (tail-call optimisation)&lt;/strong&gt;: an optimisation some runtimes perform — if a call is in tail
position, reuse the current stack frame instead of pushing a new one. The recursion becomes
as cheap as a loop, with constant stack depth.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="part-1--spot-the-tail-call-or-lack-thereof"&gt;Part 1 — Spot the tail call (or lack thereof)&lt;/h3&gt;
&lt;p&gt;Label each recursive call as &lt;strong&gt;tail&lt;/strong&gt; or &lt;strong&gt;not-tail&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>The List That Wouldn't Change</title><link>https://tristancode.com/learn/0002-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0002-puzzle/</guid><description>&lt;p&gt;A value is &lt;strong&gt;immutable&lt;/strong&gt; when it can&amp;rsquo;t be changed after it&amp;rsquo;s created. Instead of &lt;em&gt;modifying&lt;/em&gt; it, you
&lt;em&gt;build a new value&lt;/em&gt; from it and leave the original alone. (The opposite — changing a value in place —
is called &lt;strong&gt;mutation&lt;/strong&gt;.)&lt;/p&gt;
&lt;p&gt;This pairs naturally with last lesson&amp;rsquo;s idea of a &lt;strong&gt;pure function&lt;/strong&gt;: a function whose output depends
only on its inputs and which changes nothing outside itself. A function can&amp;rsquo;t very well &amp;ldquo;change
nothing&amp;rdquo; if it mutates the list you handed it.&lt;/p&gt;</description></item><item><title>The Substitution Game</title><link>https://tristancode.com/learn/0007-puzzle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tristancode.com/learn/0007-puzzle/</guid><description>&lt;p&gt;In algebra, you can replace an expression with its value without changing anything. If &lt;code&gt;y = 3 + 4&lt;/code&gt;,
you can substitute &lt;code&gt;7&lt;/code&gt; for &lt;code&gt;3 + 4&lt;/code&gt; anywhere it appears, and the math stays the same. Functions in
most programming languages &lt;em&gt;look&lt;/em&gt; like algebra — but they aren&amp;rsquo;t always.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referential transparency&lt;/strong&gt; is the property that makes the substitution safe. A function call is
&lt;em&gt;referentially transparent&lt;/em&gt; if you can always replace it with its return value and the surrounding
program behaves identically.&lt;/p&gt;</description></item></channel></rss>