﻿<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Pythonicity</title>
<link>https://coady.github.io/</link>
<atom:link href="https://coady.github.io/index.xml" rel="self" type="application/rss+xml"/>
<description>pythonicity | pīˈTHänisədē | noun the quality of being Pythonic</description>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Thu, 30 Jan 2025 00:00:00 GMT</lastBuildDate>
<item>
  <title>Go iterators</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/go-iterators.html</link>
  <description><![CDATA[ 






<section id="pythonic-go-code." class="level1">
<h1>Pythonic Go code.</h1>
<p>The long arc of language convergence continues. With generics and iterators, Go is significantly closer to Python’s reusability and expressiveness.</p>
<p>Take the built-in function <code>sum</code>. Prior to generics, a Go version would have needed separate implementations for <code>int</code> and <code>float64</code>. But that was the least of the problems. Even with a <code>Number</code> interface, it also would have been restricted to a <code>slice</code> of numbers. Realistically, one never has a slice of numbers. One has a slice of objects with a numeric field, or perhaps a <code>map</code> with numeric values.</p>
<p>Enter <a href="https://go.dev/doc/go1.23#iterators">iterators</a>. The <a href="https://go.dev/blog/range-functions">range over function</a> types are clunkier than Python generators, but to the caller the <code>range</code> interface is the same.</p>
<div id="cell-2" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;vscode&quot;,&quot;value&quot;:{&quot;languageId&quot;:&quot;shellscript&quot;}}">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span> Number interface {</span>
<span id="cb1-2">    constraints.Integer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> constraints.Float <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> constraints.Complex</span>
<span id="cb1-3">}</span>
<span id="cb1-4"></span>
<span id="cb1-5">func Sum[N Number](seq <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>.Seq[N]) N {</span>
<span id="cb1-6">    var total N</span>
<span id="cb1-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span> seq {</span>
<span id="cb1-8">        total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> value</span>
<span id="cb1-9">    }</span>
<span id="cb1-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> total</span>
<span id="cb1-11">}</span></code></pre></div></div>
</div>
<p>The standard library includes helpers <code>slices.Values</code>, <code>maps.Keys</code>, and <code>maps.Values</code>. So there is no barrier to making <code>iter.Seq</code> the standard input for iterables.</p>
<p>The Go equivalent of <a href="https://github.com/golang/go/issues/61898">itertools</a> is now inevitable. With one key difference: the lack of generator expressions will make Go more function oriented. <code>slices.ContainsFunc</code> is the equivalent of <code>any</code>; similarly the equivalent of <code>all</code> would likely embed the predicate.</p>
<div id="cell-4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;vscode&quot;,&quot;value&quot;:{&quot;languageId&quot;:&quot;shellscript&quot;}}">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">func AllFunc[E <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">any</span>](seq <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>.Seq[E], f func(E) <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>) <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> {</span>
<span id="cb2-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span> seq {</span>
<span id="cb2-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>f(value) {</span>
<span id="cb2-4">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> false</span>
<span id="cb2-5">        }</span>
<span id="cb2-6">    }</span>
<span id="cb2-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> true</span>
<span id="cb2-8">}</span></code></pre></div></div>
</div>
<p>The big question is whether <code>MapFunc</code> and <code>FilterFunc</code> become standard. They have not been added to the <code>slices</code> package - presumably because iterators were coming - though <code>DeleteFunc</code> already managed to sneak in. Just imagine Python without comprehensions; <code>map</code> and <code>filter</code> would be ubiquitous.</p>
<section id="sort-keys" class="level2">
<h2 class="anchored" data-anchor-id="sort-keys">Sort keys</h2>
<p>A related area of convergence is comparison functions. Go uses ternary <a href="https://pkg.go.dev/cmp">cmp</a> functions, and Python <a href="https://docs.python.org/3/library/functools.html#functools.cmp_to_key">used to</a>. Collective Python experience has shown that while more general, a ternary comparison is rarely needed. Even more so with the ability to reverse and stably sort.</p>
<p>Go does not have the equivalent of Python’s orderable tuples, so a ternary <code>cmp</code> will always have its place. Still, sorting by scalars is extremely common, and Go could add <a href="https://github.com/golang/go/issues/71238">key-based</a> ordering, with iterator support.</p>
<p>Note bound and unbound methods are also first class functions. So models with a standard ordering or identifier could add methods for each. Then pass <code>(*Type).Compare</code> as a <code>cmp</code> function, and <code>(*Type).Key</code> as a key function. The readability of function parameters is even better when referenced by name instead of a <code>lambda</code>.</p>
<p>The key function approach is also simpler and more efficient for <code>comparable</code> use cases. Utilities like <code>slices.CompareFunc</code> could be <code>iter.CompareBy</code> and not repeat logic.</p>
</section>
<section id="sets" class="level2">
<h2 class="anchored" data-anchor-id="sets">Sets</h2>
<p>Go does not have a built-in <code>set</code> type. The options are to use a <code>map</code> explicitly, or via a library which wraps a <code>map</code> and ignores the values. The author’s <a href="https://pkg.go.dev/github.com/coady/iterset">iterset</a> package demonstrates that a Pythonic approach is now possible. Set operations require either O(1) lookup - which maps already support - or mere iteration. So a custom <code>map</code> type is useful for efficiency, but its methods can support <code>iter.Seq</code> instead, just as Python methods do. This is both more flexible and efficient in most cases.</p>
<p>Take <code>IsSubset</code> as an example. The four interface choices have usage and performance trade-offs.</p>
<ol type="1">
<li><code>IsSubset(iter.Seq[K], iter.Seq[K])</code>: most flexible, has to convert right argument to #2</li>
<li><code>IsSubset(iter.Seq[K], map[K]V))</code>: fast, zero-copy, and flexible</li>
<li><code>IsSubset(map[K]V), iter.Seq[K]</code>: similar to #1, but converting the right argument may exit early and use less space</li>
<li><code>IsSubset(map[K]V1), map[K]V2)</code>: similar to #2, but could exit early with a size check</li>
</ol>
<p>Without function overloads, designing the interface for all use cases is a challenge. But in no case is forcing the caller to convert both arguments to <code>map[K]struct{}</code> first an improvement.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Go has just started to include iterator utilities like <code>slices.Sorted{Func}</code>. Iterators are going to have a transformative effect on readability.</p>


</section>
</section>

 ]]></description>
  <category>go</category>
  <guid>https://coady.github.io/posts/go-iterators.html</guid>
  <pubDate>Thu, 30 Jan 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GraphQL cursors</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/graphql-cursors.html</link>
  <description><![CDATA[ 






<section id="contrarian-view-on-cursor-based-pagination." class="level1">
<h1>Contrarian view on cursor-based pagination.</h1>
<p><a href="https://graphql.org">GraphQL</a> documentation recommends <a href="https://graphql.org/learn/pagination/#pagination-and-edges">cursor-based pagination</a>, and it has subsequently become a popular standard.</p>
<blockquote class="blockquote">
<p>In general, we’ve found that cursor-based pagination is the most powerful of those designed. Especially if the cursors are opaque, either offset or ID-based pagination can be implemented using cursor-based pagination (by making the cursor the offset or the ID), and using cursors gives additional flexibility if the pagination model changes in the future. As a reminder that the cursors are opaque and that their format should not be relied upon, we suggest base64 encoding them. …</p>
</blockquote>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode graphql code-with-copy"><code class="sourceCode graphql"><span id="cb1-1">{</span>
<span id="cb1-2">  hero {</span>
<span id="cb1-3">    name</span>
<span id="cb1-4">    friends(first: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) {</span>
<span id="cb1-5">      totalCount</span>
<span id="cb1-6">      edges {</span>
<span id="cb1-7">        node {</span>
<span id="cb1-8">          name</span>
<span id="cb1-9">        }</span>
<span id="cb1-10">        cursor</span>
<span id="cb1-11">      }</span>
<span id="cb1-12">      pageInfo {</span>
<span id="cb1-13">        endCursor</span>
<span id="cb1-14">        hasNextPage</span>
<span id="cb1-15">      }</span>
<span id="cb1-16">    }</span>
<span id="cb1-17">  }</span>
<span id="cb1-18">}</span></code></pre></div></div>
<p>There are several oversights with this well-intentioned advice.</p>
<section id="cursors-and-state" class="level2">
<h2 class="anchored" data-anchor-id="cursors-and-state">Cursors and state</h2>
<p>Cursors imply state, at least they used to. A <a href="https://en.wikipedia.org/wiki/Cursor_(databases)">database cursor</a> is used for iterating over <em>a result set</em>. Meaning it has transactional integrity to pick up where it left off.</p>
<p><strong><em>The vast majority of GraphQL APIs are inherently stateless.</em></strong> The “cursor” is being decoded as input to a new request, and offers no guarantees. From this observation, the advice falls apart.</p>
<p>The problem with stateless pagination is inconsistency; items may shift, appear, or disappear. Which gives the client the perception of missing or duplicate items. This happens regardless of whether the pagination is offset or ID based. Arguably worse in the case of IDs, since the reference can move arbitrarily or be gone.</p>
<p>Cursors don’t solve the consistency problem; they give the client the false impression of solving the problem.</p>
</section>
</section>
<section id="opaqueness-and-compatibility" class="level1">
<h1>Opaqueness and compatibility</h1>
<p>The claim is that an opaque cursor is compatible across changes. Changed to do what exactly, would be the more relevant question.</p>
<p>Taking a step back, what is the problem being solved here? We assume there is a list of items, with an inherent ordering, and too many to return to the client with acceptable performance.</p>
<p>Given those assumptions, the first obvious step is an optional size limit. That is not in dispute; the disagreement if over the “offset”. A simple and versatile solution is a range filter over whatever field(s) is relevant to ordering. This is not even remotely controversial when the field in question has a name like <code>date</code>. In other words, “pagination” is not necessarily the problem that needs solving.</p>
<p>Range filters with a size limit are sufficient to implement pagination, and new optional filters are always backwards compatible. They also offer the flexibility of search, whereas cursors can only be used iteratively. And what if the client does not want visibility into the range filters? That is exactly what <code>offset</code> is for; offset is a range filter over an implied <code>index</code> field.</p>
<p>There is a reason why the recommendation does not offer a useful example of this supposed compatibility; there isn’t one. The advice is equivocating on the ambiguity of an <code>after: $ID</code> filter. Is the ID field relevant to the ordering?</p>
<ul>
<li>If yes, then it is just another range filter</li>
<li>If no, then it is just another placeholder for index</li>
</ul>
<p>There is no third case. There is no future secret field that relates to ordering, is relevant to the client, but somehow still opaque to the client.</p>
<p><strong><em>Stateless pagination is a combination of range filters and size limits</em></strong>. No matter what the input fields are called. A true stateful is cursor is opaque precisely because it does not represent any known field.</p>
<section id="next-optimization" class="level2">
<h2 class="anchored" data-anchor-id="next-optimization">Next optimization</h2>
<p>The “next” piece of advice is that the cursor implementation should indicate whether another request is worthwhile. Again, in a stateless API, the server can make no such guarantee.</p>
<p>If the server can provide a total count, by all means do so. It solves the “next” problem, and is more generally useful.</p>
<p>If it is not feasible for the server to provide a total count, how is it going to implement whether there are more items? At the data layer, it is going to stop processing at <em>N + 1</em> items instead of the requested <em>N</em>. The client could do that too. Instead of requesting the next 10, it could <a href="https://en.wikipedia.org/wiki/Up_to_eleven">go to 11</a>.</p>
<p>Better yet, why stop at the server optimizing for <em>N + 0</em>? If it knows there is just 1 more item, why not go ahead and include that last one too. <em>N + 2</em> anyone? Obsessing over the last “next” is a pointless micro-optimization, all the more so because it is irrelevant whenever the total count is not coincidentally a multiple of <em>N</em>. If <em>N</em> is arbitrary, then optimizing for a particular residue <em>mod N</em> is clearly arbitrary.</p>
</section>
<section id="api-design" class="level2">
<h2 class="anchored" data-anchor-id="api-design">API design</h2>
<p>Not only is there no good reason to blindly add opaque cursors, there is also no reason to add range filters before needed. A size limit alone solves the first order of magnitude of performance issues. If a client requests the first 10 items, then needs the next 10, actually pressure test whether it is unreasonable to request the first 20. The advantage is the client then has a consistent snapshot of the first 20 regardless of changes, which could provide a better user experience.</p>
<p>A simple strategy for pagination: start with none. Then proceed to next steps as performance warrants.</p>
<ol type="1">
<li>size limit</li>
<li>range filter on known field(s)</li>
<li>offset</li>
</ol>
<p>In the unlikely event your API is stateful, you didn’t need this advice because you already had a cursor. Otherwise, cursors are an overly-complicated useless abstraction.</p>


</section>
</section>

 ]]></description>
  <category>graphql</category>
  <guid>https://coady.github.io/posts/graphql-cursors.html</guid>
  <pubDate>Sun, 09 Jun 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Packaging rundown</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/packaging-rundown.html</link>
  <description><![CDATA[ 






<section id="companion-guide-to-the-python-packaging-tutorial." class="level1">
<h1>Companion guide to the Python <a href="https://packaging.python.org/en/latest/tutorials/packaging-projects/">packaging tutorial</a>.</h1>
<p>This is not an <a href="https://drivendata.co/blog/python-packaging-2023">overview of packaging</a>, nor a <a href="https://pradyunsg.me/blog/2023/01/21/thoughts-on-python-packaging/">history of the tooling</a>. The intended audience is an author of a simple package who merely wants to publish it on the <a href="https://pypi.org">package index</a>, without being forced to make uninformed choices.</p>
<section id="build-backends" class="level2">
<h2 class="anchored" data-anchor-id="build-backends">Build backends</h2>
<p>The crux of the <a href="https://pradyunsg.me/blog/2023/01/21/thoughts-on-python-packaging/#pick-from-n-equivalent-choices-is-really-bad-ux">poor user experience</a> is <a href="https://packaging.python.org/en/latest/tutorials/packaging-projects/#choosing-a-build-backend">choosing a build backend</a>. The reader at this stage does not know what a “build backend” is, and moreover does not care.</p>
<p>The 4 backends in the tutorial are described here in their presented order. An example snippet of a <code>pyproject.toml</code> file is included, mostly assuming defaults, with a couple common options:</p>
<ul>
<li><a href="https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#static-vs-dynamic-metadata">dynamic version</a></li>
<li>package data for <a href="https://peps.python.org/pep-0561/#packaging-type-information">type information</a></li>
</ul>
<section id="hatchling" class="level3">
<h3 class="anchored" data-anchor-id="hatchling"><a href="https://pypi.org/project/hatchling/">hatchling</a></h3>
<p><a href="https://pepy.tech/project/hatchling"><img src="https://img.shields.io/pypi/dm/hatchling.svg" class="img-fluid" alt="image"></a> - 83 kB with 4 dependencies</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode toml code-with-copy"><code class="sourceCode toml"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">requires</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hatchling"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">build-backend</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hatchling.build"</span></span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[tool.hatch.build.targets.sdist]</span></span>
<span id="cb1-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">include</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;package&gt;/*"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[tool.hatch.version]</span></span>
<span id="cb1-8"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">path</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;package&gt;/__init__.py"</span></span></code></pre></div></div>
<p>Part of - not to be confused with - the project manager <a href="https://hatch.pypa.io/latest/">Hatch</a>.</p>
<p>The source distribution section is included because by default hatchling ostensibly includes <a href="https://hatch.pypa.io/latest/plugins/builder/sdist/#default-file-selection">all files that are not ignored</a>. However, it only <a href="https://hatch.pypa.io/latest/config/build/#vcs">abides by the root .gitignore</a>. It will include virtual environments, if not <a href="https://hatch.pypa.io/dev/history/hatchling/#hatchling-v1.24.2">named .venv</a>. For a project that advocates <a href="https://hatch.pypa.io/latest/why/#build-backend">sensible defaults</a>, this is surprising behavior and a security flaw. Even if <a href="https://github.com/pypa/hatch/issues/304">the issue</a> is fixed, it will presumably include untracked files and clearly omissible directories such as <code>.github</code>.</p>
</section>
<section id="setuptools" class="level3">
<h3 class="anchored" data-anchor-id="setuptools"><a href="https://pypi.org/project/setuptools/">setuptools</a></h3>
<p><a href="https://pepy.tech/project/setuptools"><img src="https://img.shields.io/pypi/dm/setuptools.svg" class="img-fluid" alt="image"></a> - 894 kB with 0 dependencies</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode toml code-with-copy"><code class="sourceCode toml"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[build-system]</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">requires</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"setuptools&gt;=61.0"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb2-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">build-backend</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"setuptools.build_meta"</span></span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[tool.setuptools]</span></span>
<span id="cb2-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">packages</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;package&gt;"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[tool.setuptools.dynamic]</span></span>
<span id="cb2-9"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">version</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">attr</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;package&gt;.__version__"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<p>The original build tool, and previously the de facto standard. It is no longer commonly included in Python distributions, so they are all on equal footing with respect to needing installation.</p>
<p>Setuptools may require explicitly specifying the package, depending on what directories are present. It also includes legacy “.egg” and “setup.cfg” files, which a modern user will not be familiar with.</p>
</section>
<section id="flit-core" class="level3">
<h3 class="anchored" data-anchor-id="flit-core"><a href="https://pypi.org/project/flit-core/">flit-core</a></h3>
<p><a href="https://pepy.tech/project/flit_core"><img src="https://img.shields.io/pypi/dm/flit_core.svg" class="img-fluid" alt="image"></a> - 63 kB with 0 dependencies</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode toml code-with-copy"><code class="sourceCode toml"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[build-system]</span></span>
<span id="cb3-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">requires</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flit-core&gt;=3.4"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb3-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">build-backend</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flit_core.buildapi"</span></span></code></pre></div></div>
<p>Part of the <a href="https://flit.pypa.io/en/stable/">Flit</a> tool for publishing packages.</p>
<p>Flit automatically supports dynamic versions (and descriptions), and includes the source directory with data files in the source distribution.</p>
</section>
<section id="pdm-backend" class="level3">
<h3 class="anchored" data-anchor-id="pdm-backend"><a href="https://pypi.org/project/pdm-backend/">pdm-backend</a></h3>
<p><a href="https://pepy.tech/project/pdm-backend"><img src="https://img.shields.io/pypi/dm/pdm-backend.svg" class="img-fluid" alt="image"></a> - 101 kB with 0 dependencies</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode toml code-with-copy"><code class="sourceCode toml"><span id="cb4-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">requires</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdm-backend"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb4-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">build-backend</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdm.backend"</span></span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[tool.pdm]</span></span>
<span id="cb4-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">version</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">source</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"file"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">, </span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">path</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;package&gt;/__init__.py"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<p>Part of - not to be confused with - the project manager <a href="https://pdm-project.org/">PDM</a>.</p>
<p>PDM automatically includes the source and test directories, with data files, in the source distribution.</p>
</section>
</section>
<section id="evaluations" class="level2">
<h2 class="anchored" data-anchor-id="evaluations">Evaluations</h2>
<section id="popularity-and-endorsements" class="level3">
<h3 class="anchored" data-anchor-id="popularity-and-endorsements">Popularity and endorsements</h3>
<p>The popularity of Setuptools should be discounted because of its history. The popularity of Hatchling and PDM-backend is clearly influenced by their respective parent projects. PDM has significantly less downloads than the others, but they are all popular enough to expect longevity.</p>
<p>Setuptools, Hatch, and Flit are all under the <a href="https://github.com/pypa/">packaging authority umbrella</a>, though as the previously cited article points out, <a href="https://pradyunsg.me/blog/2023/01/21/thoughts-on-python-packaging/#not-a-pypa-project">PyPA affiliation does not indicate much</a>.</p>
<p>The tutorial “defaults” to Hatchling, which presumably is not intended as an endorsement, but will no doubt be interpreted as such.</p>
</section>
<section id="size-and-dependencies" class="level3">
<h3 class="anchored" data-anchor-id="size-and-dependencies">Size and dependencies</h3>
<p>Setuptools is by far the largest; no surprise since it is much more than a build backend. Hatchling is the only one with dependencies, but the 3 modern ones seem appropriately lightweight.</p>
</section>
<section id="file-selection" class="level3">
<h3 class="anchored" data-anchor-id="file-selection">File selection</h3>
<p>Wheels have a standard layout, but source distributions do not. Whether <a href="https://discuss.python.org/t/should-sdists-include-docs-and-tests/14578">sdist should include docs and tests</a> is a matter of debate.</p>
<p>There was a time when open source software meant “distributed with an open source license”, so the source distribution was the primary way to acquire the code. This all seems anachronistic in the age of distributed version control and public collaboration. Not to mention wheels are zip files which have the source code.</p>
<p>One <a href="https://discuss.python.org/t/should-sdists-include-docs-and-tests/14578/4">piece of advice</a> is that the sdist should be buildable. Generated portable files could be included, thereby not needing the tools that generate them. But for a simple (read pure) Python project, that is not particularly relevant.</p>
<p>There is another issue with backends creating different artifacts when using their own build commands. This rundown only evaluated <code>python -m build</code>.</p>
</section>
<section id="metadata" class="level3">
<h3 class="anchored" data-anchor-id="metadata">Metadata</h3>
<p>The modern 3 implicitly support data files. All 4 support dynamic versioning in some manner. Then again, maybe the <code>__version__</code> attribute is no longer the leading convention among the 7 options for <a href="https://packaging.python.org/en/latest/guides/single-sourcing-package-version/">single-sourcing the version</a>. Now that <a href="https://docs.python.org/3.10/library/importlib.metadata.html">importlib.metadata</a> is no longer provisional, is that preferred?</p>
</section>
</section>
<section id="recommendations" class="level2">
<h2 class="anchored" data-anchor-id="recommendations">Recommendations</h2>
<p>It would be disingenuous to not end with recommendations, since the refusal to - in a document titled <a href="https://packaging.python.org/en/latest/guides/tool-recommendations/">tool recommendations</a> - is the problem. The PyPA endorses <code>pip</code>, <code>build</code>, and <code>twine</code> as standard tools, even though there are alternatives.</p>
<p>Author’s disclosures: I am a long-time Python developer of several packages, and a couple with <a href="https://docs.python.org/3/extending/extending.html">extension modules</a>. I use no project management tools, and am not affiliated with any of these projects.</p>
<ol type="1">
<li><em>flit-core</em> - No criticisms. The dynamic version and description feature are a plus; not having any flit-specific sections feels like less coupling.</li>
<li><em>pdm-backend</em> - No criticisms. A natural choice if one wants tests in the source distribution.</li>
<li><em>hatchling</em> - The file selection issue is significant. Users need a warning that they should include an sdist section and check their tarballs. Many are going to have unnecessarily large distributions, and someone with a local secrets directory - whether ignored or untracked - is going to have a seriously bad day.</li>
<li><em>setuptools</em> - Perpetually handicapped by backwards compatibility. The only advantage setuptools had was being already installed. It may be time to disavow it for new projects without extension modules.</li>
</ol>
<p>My projects currently use <code>setuptools</code> for purely historical reasons. For new projects, I would likely use <code>flit-core</code>. I may switch-over existing projects, though there is really no incentive to.</p>
<p>Unless a standard emerges, of course.</p>
</section>
<section id="addendum" class="level2">
<h2 class="anchored" data-anchor-id="addendum">Addendum</h2>
<p>A meta case could be made for Flit(-core) as well: that its limited scope and independence from a project manager is itself an asset. Whereas choosing Hatch(ling) or PDM(-backend) feels like picking a side. Flit <a href="https://flit.pypa.io/en/latest/rationale.html">can position itself</a> as the minimalist choice for those who resent having to choose.</p>
<p>And yet the situation is even more absurd. There has been an <a href="https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/#fallback-behaviour">under-documented default</a> the entire time. The default is the legacy mode of setuptools, which differs only in its path setup. If one forgoes a dynamic <code>__version__</code> attribute - which perhaps <code>importlib.metadata</code> was intended to do - then one can have a <code>pyproject.toml</code> with no references to build backends.</p>


</section>
</section>

 ]]></description>
  <category>core</category>
  <guid>https://coady.github.io/posts/packaging-rundown.html</guid>
  <pubDate>Sun, 12 May 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GraphQL root fields</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/graphql-root-fields.html</link>
  <description><![CDATA[ 






<section id="there-is-no-such-thing-as-a-root-field." class="level1">
<h1>There is no such thing as a “root field”.</h1>
<p>There is a common - seemingly universal - misconception that <a href="https://graphql.org">GraphQL</a> root fields are somehow special, in both usage and implementation. The better conceptual model is that there are root <em>types</em>, and all types have fields. The difference is not just semantics; it leads to actual misunderstandings.</p>
<section id="multiple-queries" class="level2">
<h2 class="anchored" data-anchor-id="multiple-queries">Multiple queries</h2>
<p>A common beginner question is “can there be multiple queries in a request”. The question would be better phrased as “can multiple fields on the root query type be requested”. The answer is of course, because requesting multiple fields on a type is normal. The implementation would have to go out of its way to restrict that behavior on just the root type. The only need for further clarity would be to <a href="https://graphql.org/learn/queries/#aliases">introduce aliases</a> for duplicate fields.</p>
</section>
<section id="flat-namespace" class="level2">
<h2 class="anchored" data-anchor-id="flat-namespace">Flat namespace</h2>
<p>GraphQL types share a global namespace, causing conflicts when federating multiple graphs. Nothing can be done about that unless GraphQL adopts <a href="https://github.com/graphql/graphql-spec/issues/163">namespaces</a>.</p>
<p>But many APIs design the root query type to have unnecessarily flat fields. One often sees a hierarchy of types and fields below the root, but the top-level fields resemble a loose collections of functions. Verbs at the top level; nouns the rest of the way down. This design choice appears to be in a feedback loop with the notion of “root fields”.</p>
<p>Even the convention of calling the root query type <code>Query</code> demonstrates a lack of specificity. In a service-oriented architecture, a particular service might be more narrowly defined.</p>
</section>
<section id="mutations" class="level2">
<h2 class="anchored" data-anchor-id="mutations">Mutations</h2>
<p>Top-level mutation fields are special in one aspect: they are <a href="https://graphql.org/learn/queries/#multiple-fields-in-mutations">executed in order</a>. This has resulted in even flatter namespaces for mutations,</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode graphql code-with-copy"><code class="sourceCode graphql"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">mutation</span> {</span>
<span id="cb1-2">    createUser <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># executed first</span></span>
<span id="cb1-3">    deleteUser</span>
<span id="cb1-4">}</span></code></pre></div></div>
<p>This is not necessary, but seems widely believed that it is. Nested mutations work just fine.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode graphql code-with-copy"><code class="sourceCode graphql"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">mutation</span> {</span>
<span id="cb2-2">    user {</span>
<span id="cb2-3">        create <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># executed in arbitrary order</span></span>
<span id="cb2-4">        delete</span>
<span id="cb2-5">    }</span>
<span id="cb2-6">}</span></code></pre></div></div>
<p>If the underlying reason is truly execution order, the client could be explicit instead.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode graphql code-with-copy"><code class="sourceCode graphql"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">mutation</span> {</span>
<span id="cb3-2">    created: user { <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># executed first</span></span>
<span id="cb3-3">        create</span>
<span id="cb3-4">    }</span>
<span id="cb3-5">    deleted: user {</span>
<span id="cb3-6">        delete</span>
<span id="cb3-7">    }</span>
<span id="cb3-8">}</span></code></pre></div></div>
<p>There is no reason it has to influence API design.</p>
</section>
<section id="static-methods" class="level2">
<h2 class="anchored" data-anchor-id="static-methods">Static methods</h2>
<p>At the library level, the effect is top-level resolvers are implemented as functions (or static methods), whereas all other resolver are methods. This may lead to redundant or inefficient implementations, is oddly inconsistent, and is <a href="https://graphql.org/learn/execution/#root-fields--resolvers">contrary to the documentation</a>.</p>
<blockquote class="blockquote">
<p>A resolver function receives four arguments:</p>
<p><code>obj</code> The previous object, which for a field on the root Query type is often not used.</p>
</blockquote>
<p>Sure, “often not used” by the developer of the API. That does not mean “should be unset” by the GraphQL library, but that is what has happened. Some libraries even <a href="https://gqlgen.com/getting-started/#implement-the-resolvers">exclude the object parameter</a> entirely. In object-oriented libraries like <a href="https://strawberry.rocks">strawberry</a>, the code looks unnatural.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> strawberry</span>
<span id="cb4-2"> </span>
<span id="cb4-3"> </span>
<span id="cb4-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.type</span></span>
<span id="cb4-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Query:</span>
<span id="cb4-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.field</span></span>
<span id="cb4-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> instance(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb4-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, Query)</span>
<span id="cb4-9"></span>
<span id="cb4-10"></span>
<span id="cb4-11">schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strawberry.Schema(Query)</span>
<span id="cb4-12">query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'{ instance }'</span></span>
<span id="cb4-13">schema.execute_sync(query).data</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>{'instance': None}</code></pre>
</div>
</div>
<p>Strawberry allows omitting <code>self</code> for this reason, creating an implicit <code>staticmethod</code>.</p>
</section>
<section id="root-values" class="level2">
<h2 class="anchored" data-anchor-id="root-values">Root values</h2>
<p>Libraries which follow the <a href="https://graphql.org/graphql-js/#writing-code">reference javascript implementation</a> allow setting the root value explicitly.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">schema.execute_sync(query, root_value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Query()).data</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>{'instance': True}</code></pre>
</div>
</div>
<p>Strawberry unofficially supports supplying an instance, but it has no effect.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strawberry.Schema(Query())</span>
<span id="cb8-2">schema.execute_sync(query).data</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>{'instance': None}</code></pre>
</div>
</div>
<p>And of course <code>self</code> can be of any type.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">schema.execute_sync(query, root_value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>...).data</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>{'instance': False}</code></pre>
</div>
</div>
<p>Moreover, the <code>execute</code> functions are for internal usage. Each library will vary in how to configure the root in a production application. Strawberry requires subclassing the application type.</p>
<div id="cell-10" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> strawberry.asgi</span>
<span id="cb12-2"></span>
<span id="cb12-3"></span>
<span id="cb12-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> GraphQL(strawberry.asgi.GraphQL):</span>
<span id="cb12-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, root):</span>
<span id="cb12-6">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(strawberry.Schema(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(root)))</span>
<span id="cb12-7">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.root_value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> root</span>
<span id="cb12-8"></span>
<span id="cb12-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">async</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_root_value(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, request):</span>
<span id="cb12-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.root_value</span></code></pre></div></div>
</div>
</section>
<section id="example" class="level2">
<h2 class="anchored" data-anchor-id="example">Example</h2>
<p>Consider a more practical example where data is loaded, and clearly should not be reloaded on each request.</p>
<div id="cell-12" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.type</span></span>
<span id="cb13-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Dictionary:</span>
<span id="cb13-3">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, source<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/usr/share/dict/words'</span>):</span>
<span id="cb13-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.words <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {line.strip() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> line <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(source)}</span>
<span id="cb13-5"></span>
<span id="cb13-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.field</span></span>
<span id="cb13-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> is_word(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, text: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb13-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> text <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.words</span></code></pre></div></div>
</div>
<p>Whether <code>Dictionary</code> is the query root - or attached to the query root - it should be instantiated only once. Of course it can be cached, but again there is a more natural way to write this outside the context of GraphQL.</p>
<div id="cell-14" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.type</span></span>
<span id="cb14-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Query:</span>
<span id="cb14-3">    dictionary: Dictionary</span>
<span id="cb14-4"></span>
<span id="cb14-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb14-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.dictionary <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Dictionary()</span></code></pre></div></div>
</div>
<p>Caching, context values, and root values are all clunky workarounds compared to the consistency of letting the root be <code>Query()</code> instead of <code>Query</code>. The applications which do not require this feature would never notice the difference.</p>
<p>The notion of “root fields” behaving as “top-level functions” has resulted in needless confusion, poorer API design, and incorrect implementations.</p>


</section>
</section>

 ]]></description>
  <category>graphql</category>
  <guid>https://coady.github.io/posts/graphql-root-fields.html</guid>
  <pubDate>Fri, 12 Apr 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Composition vs. inheritance</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/composition-vs-inheritance.html</link>
  <description><![CDATA[ 






<section id="contrarian-view-on-composition-over-inheritance." class="level1">
<h1>Contrarian view on composition over inheritance.</h1>
<p>The conventional wisdom is to prefer <a href="https://en.wikipedia.org/wiki/Composition_over_inheritance">composition over inheritance</a>. More specifically to use <a href="https://en.wikipedia.org/wiki/Delegation_pattern">delegation</a> over single inheritance.</p>
<p>Like the recommendation on <a href="closing-files.html">closing files</a>, the advice is well-intentioned but omits the fact that Python does not support it well. Python has no mechanism for embedding or forwarding methods. And the despite its famous <a href="https://docs.python.org/3/glossary.html#term-duck-typing">duck-typing</a>, there are many cases where a type must be subclassed to be <a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle">substitutable</a> (particularly if implemented in CPython).</p>
<p>The below example comes from a popular <a href="https://pycon.org">PyCon</a> talk called <a href="https://www.youtube.com/watch?v=wf-BqAjZb8M">Beyond PEP 8</a>. The goal is to <a href="https://www.shawnxli.com/posts/beyond-pep-8/">adapt a Java-esque interface</a> into pythonic code.</p>
<section id="original-implementation" class="level2">
<h2 class="anchored" data-anchor-id="original-implementation">Original implementation</h2>
<div id="cell-2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> jnettool.tools.elements.NetworkElement</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> jnettool.tools.Routing</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> jnettool.tools.RouteInsector</span>
<span id="cb1-4"></span>
<span id="cb1-5">ne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> jnettool.tools.elements.NetworkElement(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'171.0.2.45'</span>)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb1-8">    routing_table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ne.getRoutingTable()</span>
<span id="cb1-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> jnettool.tools.elements.MissingVar:</span>
<span id="cb1-10">    logging.exception(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No routing table found'</span>)</span>
<span id="cb1-11">    ne.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rollback'</span>)</span>
<span id="cb1-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb1-13">    num_routes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> routing_table.getSize()</span>
<span id="cb1-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> RToffset <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(num_routes):</span>
<span id="cb1-15">        route <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> routing_table.getRouteByIndex(RToffset)</span>
<span id="cb1-16">        name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> route.getName()</span>
<span id="cb1-17">        ipaddr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> route.getIPAddr()</span>
<span id="cb1-18">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%15s</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> -&gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%s</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> (name, ipaddr)</span>
<span id="cb1-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">finally</span>:</span>
<span id="cb1-20">    ne.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'commit'</span>)</span>
<span id="cb1-21">    ne.disconnect()</span></code></pre></div></div>
</div>
</section>
<section id="proposed-interface" class="level2">
<h2 class="anchored" data-anchor-id="proposed-interface">Proposed interface</h2>
<div id="cell-4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> nettools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> NetworkElement</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> NetworkElement(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'171.0.2.45'</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> ne:</span>
<span id="cb2-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> route <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ne.routing_table:</span>
<span id="cb2-5">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%15s</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> -&gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%s</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> (route.name, route.ipaddr)</span></code></pre></div></div>
</div>
</section>
<section id="proposed-solution" class="level2">
<h2 class="anchored" data-anchor-id="proposed-solution">Proposed solution</h2>
<div id="cell-6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> jnetool.tools.elements.NetworkElement</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> jnetool.tools.Routing</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NetworkElementError(<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span>):</span>
<span id="cb3-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NetworkElement(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">object</span>):</span>
<span id="cb3-8"></span>
<span id="cb3-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ipaddr):</span>
<span id="cb3-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ipaddr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ipaddr</span>
<span id="cb3-11">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> jnetool.tools.elements.NetworkElement(ipaddr)</span>
<span id="cb3-12"></span>
<span id="cb3-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb3-14">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> routing_table(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb3-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> RoutingTable(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldne.getRoutingTable())</span>
<span id="cb3-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> jnetool.tools.elements.MissingVar:</span>
<span id="cb3-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> NetworkElementError(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No routing table found'</span>)</span>
<span id="cb3-19"></span>
<span id="cb3-20">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__enter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-21">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span></span>
<span id="cb3-22"></span>
<span id="cb3-23">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__exit__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, exctype, excinst, exctb):</span>
<span id="cb3-24">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> exctype <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> NetworkElementError:</span>
<span id="cb3-25">            logging.exception(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No routing table found'</span>)</span>
<span id="cb3-26">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldne.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rollback'</span>)</span>
<span id="cb3-27">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb3-28">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldne.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'commit'</span>)</span>
<span id="cb3-29">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldne.disconnect()</span>
<span id="cb3-30"></span>
<span id="cb3-31">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__repr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%s</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%r</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">)'</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__class__</span>.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ipaddr)</span>
<span id="cb3-33"></span>
<span id="cb3-34"></span>
<span id="cb3-35"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> RoutingTable(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">object</span>):</span>
<span id="cb3-36"></span>
<span id="cb3-37">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, oldrt):</span>
<span id="cb3-38">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldrt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> oldrt</span>
<span id="cb3-39"></span>
<span id="cb3-40">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__len__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-41">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldrt.getSize()</span>
<span id="cb3-42"></span>
<span id="cb3-43">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, index):</span>
<span id="cb3-44">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-45">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">IndexError</span></span>
<span id="cb3-46">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Route(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.oldrt.getRouteByIndex(index))</span>
<span id="cb3-47"></span>
<span id="cb3-48"></span>
<span id="cb3-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Route(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">object</span>):</span>
<span id="cb3-50"></span>
<span id="cb3-51">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, old_route):</span>
<span id="cb3-52">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.old_route <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> old_route</span>
<span id="cb3-53"></span>
<span id="cb3-54">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb3-55">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> name(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-56">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.old_route.getName()</span>
<span id="cb3-57"></span>
<span id="cb3-58">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb3-59">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ipaddr(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-60">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.old_route.getIPAddr()</span></code></pre></div></div>
</div>
<p>No dispute that the interface is superior, but the implementation is using delegation as if it is dogma. The usage pattern has to be extrapolated from one example, but here are the issues:</p>
<ul>
<li>Custom exceptions are not helpful if they do nothing. The consumer of this code <em>does not</em> use <code>NetworkElementError</code>, and has lost the traceback if it did. Error hiding is not error handling.</li>
<li>Comparing classes with <code>==</code> is widely considered an anti-pattern, as opposed to <code>is</code> or <code>issubclass</code>.</li>
<li>The <code>Route</code> object doesn’t need to delegate. There is no reason to assume that the underlying attribute access must be lazy, particularly since the iteration could be lazy instead. A named tuple or dataclass would suffice here.</li>
<li>The <code>RoutingTable</code> object doesn’t need to delegate. There is no need to support random access or lazy evaluation. Its only addition to the interface is to be sequence-like, which could be trivially accomplished by a sequence.</li>
<li>The <code>NetworkElement</code> doesn’t need to delegate. It has the same name, same constructor, a <code>repr</code> designed to appear as the original, and only extends behavior. If this doesn’t pass as an <code>is-a</code> relation, nothing does.</li>
</ul>
</section>
<section id="simple-solution" class="level2">
<h2 class="anchored" data-anchor-id="simple-solution">Simple solution</h2>
<div id="cell-8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> collections</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> jnettool.tools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> elements</span>
<span id="cb4-3"></span>
<span id="cb4-4">Route <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> collections.namedtuple(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Route'</span>, [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ipaddr'</span>])</span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NetworkElement(elements.NetworkElement):</span>
<span id="cb4-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb4-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> routing_table(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb4-9">        table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.getRoutingTable()</span>
<span id="cb4-10">        routes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(table.getRouteByIndex, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(table.getSize()))</span>
<span id="cb4-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [Route(route.getName(), route.getIPAddr()) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> route <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> routes]</span>
<span id="cb4-12"></span>
<span id="cb4-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__enter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb4-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span></span>
<span id="cb4-15"></span>
<span id="cb4-16">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__exit__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, exc_type, exc_val, exc_tb):</span>
<span id="cb4-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(exc_val, elements.MissingVar):</span>
<span id="cb4-18">            logging.exception(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"No routing table found"</span>)</span>
<span id="cb4-19">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rollback'</span>)</span>
<span id="cb4-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb4-21">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cleanup(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'commit'</span>)</span>
<span id="cb4-22">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.disconnect()</span></code></pre></div></div>
</div>
<p>Which version is more maintainable? Surely the simpler one.</p>
<p>Which version is more extensible? Well, by whom? The implementor can extend either just as easily. The caller can use the inherited version without losing any functionality.</p>
<p>So a better question might be which version is more flexible or reusable? Surely the inherited version, because the delegated version would need to access <code>oldne</code>. Even naming the delegate is a pain point, because one has to decide if it is a part of the public interface or not. Should it have 0, 1, or 2 leading underscores? Delegation is often touted as achieving both encapsulation and extensibility, despite being opposing goals.</p>
<p>Finally, there is also a simpler interface, again with the caveat that there is only one usage example. An iterable of 2-field objects, one of which is called <code>name</code>, and “points to” the other field. Sounds like a mapping.</p>
<div id="cell-10" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NetworkElement(elements.NetworkElement):</span>
<span id="cb5-2">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb5-3">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> routing_table(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb5-4">        table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.getRoutingTable()</span>
<span id="cb5-5">        routes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(table.getRouteByIndex, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(table.getSize()))</span>
<span id="cb5-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {route.getName(): route.getIPAddr() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> route <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> routes}</span>
<span id="cb5-7">    ...</span></code></pre></div></div>
</div>


</section>
</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/composition-vs-inheritance.html</guid>
  <pubDate>Sat, 18 Nov 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Decorator overuse</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/decorator-overuse.html</link>
  <description><![CDATA[ 






<section id="decorators-versus-blocks-and-partial-functions." class="level1">
<h1>Decorators versus blocks and partial functions.</h1>
<p>Decorators are a beloved feature of Python, but like any good thing can be overused. The key is acknowledging that decorators are <a href="https://docs.python.org/3/glossary.html#term-decorator">just functions</a>.</p>
<blockquote class="blockquote">
<p>A function returning another function, usually applied as a function transformation using the <span class="citation" data-cites="wrapper">@wrapper</span> syntax. Common examples for decorators are classmethod() and staticmethod().</p>
<p>The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> f(arg):</span>
<span id="cb1-2">   ...</span>
<span id="cb1-3">f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">staticmethod</span>(f)</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@staticmethod</span></span>
<span id="cb1-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> f(arg):</span>
<span id="cb1-7">   ...</span></code></pre></div></div>
</blockquote>
<section id="renamed" class="level2">
<h2 class="anchored" data-anchor-id="renamed">Renamed</h2>
<p>So the critical feature of the <code>@</code> syntax is to retain the defined object’s name; otherwise it is just a function call. Which leads to the first example of overuse: defining a new object just to change the name. Consider this example adapted from a <a href="https://github.com/psf/requests">popular project</a>.</p>
<div id="cell-2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Response:</span>
<span id="cb2-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__bool__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb2-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ok</span>
<span id="cb2-4"></span>
<span id="cb2-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb2-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ok(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb2-7">        ...</span></code></pre></div></div>
</div>
<p>Since a <code>property</code> wraps a function, it is natural to make the function have the implementation instead. Then it becomes clear that the <code>property</code> does not share the same name, so why bother with <code>@</code>.</p>
<div id="cell-4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Response:</span>
<span id="cb3-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__bool__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb3-3">        ...</span>
<span id="cb3-4"></span>
<span id="cb3-5">    ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">property</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__bool__</span>)</span></code></pre></div></div>
</div>
<p>A related scenario is where the local name of the function is irrelevant, which is typical in <a href="https://docs.python.org/3/library/functools.html#functools.wraps">wrapped functions</a>:</p>
<blockquote class="blockquote">
<p><span class="citation" data-cites="functools.wraps">@functools.wraps</span>(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)</p>
<p>This is a convenience function for invoking update_wrapper() as a function decorator when defining a wrapper function. It is equivalent to partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated). For example:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;&gt;</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> wraps</span>
<span id="cb4-2"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;&gt;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> my_decorator(f):</span>
<span id="cb4-3">...     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span>wraps(f)</span>
<span id="cb4-4">...     <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwds):</span>
<span id="cb4-5">...         <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Calling decorated function'</span>)</span>
<span id="cb4-6">...         <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> f(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwds)</span>
<span id="cb4-7">...     <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> wrapper</span></code></pre></div></div>
</blockquote>
<p>The “convenience function” is useless indirection when the wrapper is immediately returned. Even the documentation points out that <code>wraps</code> is just a <code>partial</code> function. The example could be simply:</p>
<div id="cell-6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> my_decorator(f):</span>
<span id="cb5-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwds):</span>
<span id="cb5-3">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Calling decorated function'</span>)</span>
<span id="cb5-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> f(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwds)</span>
<span id="cb5-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> update_wrapper(wrapper, f)</span></code></pre></div></div>
</div>
<p>Giving <code>partial(update_wrapper, wrapped=f)</code> a short name does not make it any clearer conceptually.</p>
</section>
<section id="with-blocks" class="level2">
<h2 class="anchored" data-anchor-id="with-blocks">With blocks</h2>
<p>Another sign is if the decorator’s functionality only executes code before or after the wrapped function. Context managers are inherently more flexible by providing the same functionality for any code block. In some cases a function boundary is natural to bookend, e.g., logging or timing. The question is whether the function block is too broad a context to manage.</p>
<p>Decorators were introduced in <a href="https://nedbatchelder.com/text/which-py.html#h_25_september_19th_2006">version 2.4</a>; context managers in 2.5. All ancient history now, but decorators had a ~2 year head start. For example, transactions are a <a href="https://docs.python.org/3/whatsnew/2.5.html#writing-context-managers">seminal use case for context managers</a>, but <a href="https://www.djangoproject.com">Django</a> pre-dates 2.5, so it had a transaction decorator first. This is how <a href="https://docs.djangoproject.com/en/4.1/topics/db/transactions/">transactions are currently presented</a>:</p>
<blockquote class="blockquote">
<p>atomic is usable both as a decorator:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> django.db <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> transaction</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@transaction.atomic</span></span>
<span id="cb6-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> viewfunc(request):</span>
<span id="cb6-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This code executes inside a transaction.</span></span>
<span id="cb6-6">   do_stuff()</span></code></pre></div></div>
<p>and as a context manager:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> django.db <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> transaction</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> viewfunc(request):</span>
<span id="cb7-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This code executes in autocommit mode (Django's default).</span></span>
<span id="cb7-5">    do_stuff()</span>
<span id="cb7-6"></span>
<span id="cb7-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> transaction.atomic():</span>
<span id="cb7-8">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This code executes inside a transaction.</span></span>
<span id="cb7-9">        do_more_stuff()</span></code></pre></div></div>
</blockquote>
<p>So it has both, but the decorator is presented first, and is it a good example? Seems likely that a full request would have setup and teardown work that is unrelated to a database transaction. It is uncontroversial to want <code>try</code> blocks to be as narrow as possible. Surely there is no benefit to a request operation rolling back a vacuous transaction, nor a response operation rolling back a transaction that was committable.</p>
<p>Any context manager can be trivially transformed into a decorator; the converse is not true. And even if the function block is <em>coincidentally</em> perfect, a <code>with</code> block has negligible impact on readability. It is just indentation.</p>
</section>
<section id="partial-functions" class="level2">
<h2 class="anchored" data-anchor-id="partial-functions">Partial functions</h2>
<p>Next is a lack of appreciation of partially bound functions. Many decorator examples go out of their way to write an unnecessary <code>def</code> statement, in order to make using a decorator look natural. The below example is common in <a href="https://realpython.com/primer-on-python-decorators/#decorators-with-arguments">Python tutorials</a>.</p>
<div id="cell-8" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> functools</span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> repeat(num_times):</span>
<span id="cb8-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> decorator_repeat(func):</span>
<span id="cb8-5">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@functools.wraps</span>(func)</span>
<span id="cb8-6">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper_repeat(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb8-7">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(num_times):</span>
<span id="cb8-8">                value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb8-9">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> value</span>
<span id="cb8-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> wrapper_repeat</span>
<span id="cb8-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> decorator_repeat</span>
<span id="cb8-12"></span>
<span id="cb8-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@repeat</span>(num_times<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb8-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> greet(name):</span>
<span id="cb8-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Hello </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-16"></span>
<span id="cb8-17">greet(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello World
Hello World
Hello World
Hello World</code></pre>
</div>
</div>
<p>First the obligatory observation that abstracting a <code>for</code> loop in Python is not necessarily a good idea. But assuming that is the goal, it is still worth questioning why repeating 4 times is coupled to the name <code>greet</code>. Is <code>print</code> supposed to represent the “real” function in this example, or should the wrapped function be named <code>greet_4x</code>? It is much simpler to start with the basic functionality and postpone how to wrap it.</p>
<div id="cell-10" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> repeat(num_times, func, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb10-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(num_times):</span>
<span id="cb10-3">        value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb10-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> value</span>
<span id="cb10-5"></span>
<span id="cb10-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> greet(name):</span>
<span id="cb10-7">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Hello </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb10-8"></span>
<span id="cb10-9">repeat(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, greet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello World
Hello World
Hello World
Hello World</code></pre>
</div>
</div>
<p>We can stop there really. But even assuming that the goal is to bind the repetition, using partial functions is still simpler.</p>
<div id="cell-12" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> partial</span>
<span id="cb12-2"></span>
<span id="cb12-3">greet_4x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> partial(repeat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, greet)</span>
<span id="cb12-4">greet_4x(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello World
Hello World
Hello World
Hello World</code></pre>
</div>
</div>
<p>Not exactly the same without <code>wraps</code>, but that would be trivial to add. Futhermore it is less useful because <code>partial</code> objects can be easily introspected. Now onto the next - and dubious - assumption: that we <em>really</em> want it used as a decorator. This requires assuming the body of <code>greet</code> is not a simple call to an underlying wrapped function, and yet for some reason the repetition is supposed to be coupled to the wrapper function’s name anyway. Still simpler:</p>
<div id="cell-14" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">repeats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> partial(partial, repeat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb14-2"></span>
<span id="cb14-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@repeats</span></span>
<span id="cb14-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> greet(name):</span>
<span id="cb14-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Hello </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb14-6"></span>
<span id="cb14-7">greet(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello World
Hello World
Hello World
Hello World</code></pre>
</div>
</div>
<p>Nested partials may appear a little too clever, but they are just the flatter version of the original nested <code>repeat</code> functions. And again, none of this indirection is necessary.</p>
</section>
<section id="for-loops" class="level2">
<h2 class="anchored" data-anchor-id="for-loops">For loops</h2>
<p>A real-world example of <code>repeat</code> is <a href="https://wiki.python.org/moin/PythonDecoratorLibrary#Retry">retrying functions</a> until success, optionally with delays. A <a href="https://github.com/litl/backoff">popular one</a> uses examples like:</p>
<div id="cell-16" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@backoff.on_exception</span>(backoff.expo, requests.exceptions.RequestException)</span>
<span id="cb16-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_url(url):</span>
<span id="cb16-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> requests.get(url)</span></code></pre></div></div>
</div>
<p>The same pattern (ahem) repeats. The decorated function is a trivial wrapper around the “real” function. Why not:</p>
<div id="cell-18" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">get_url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> backoff.on_exception(backoff.expo, requests.exceptions.RequestException)(requests.get)</span></code></pre></div></div>
</div>
<p>Furthermore, <code>for</code> loops can be customized via the <code>__iter__</code> protocol, just as <code>with</code> blocks are customizable. The author’s <a href="https://coady.github.io/waiter/examples/">waiter</a> package demonstrates the same functionality with <code>for</code> loops and undecorated functions.</p>
</section>
</section>
<section id="advocacy" class="level1">
<h1>Advocacy</h1>
<p>So before assuming a decorator is the right abstraction, start with whether a <code>def</code> function is the right abstraction. Building out functionality in this progression works well:</p>
<ol type="1">
<li>code blocks: <code>with</code> and <code>for</code> and customizable</li>
<li>flat functions</li>
<li>nested functions: using <code>partial</code></li>
<li>decorated functions</li>
</ol>


</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/decorator-overuse.html</guid>
  <pubDate>Sat, 04 Mar 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GraphQL nulls</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/graphql-nulls.html</link>
  <description><![CDATA[ 






<section id="litany-against-nulls." class="level1">
<h1>Litany against nulls.</h1>
<p>The myths and misconceptions regarding null behavior in GraphQL are epic. Even <a href="http://spec.graphql.org/October2021/#sec-Non-Null.Nullable-vs-Optional">the spec</a> is wrong.</p>
<blockquote class="blockquote">
<p>Inputs (such as field arguments), are always optional by default. However a non-null input type is required. In addition to not accepting the value null, it also does not accept omission. For the sake of simplicity nullable types are always optional and non-null types are always required.</p>
</blockquote>
<p>One might pedantically ask, can a spec be wrong by definition? Yes, it can <a href="http://spec.graphql.org/October2021/#sec-Required-Arguments.Explanatory-Text">contradict</a> <a href="http://spec.graphql.org/October2021/#sec-Input-Object-Required-Fields.Explanatory-Text">itself</a>.</p>
<blockquote class="blockquote">
<p>Arguments can be required. An argument is required if the argument type is non-null and does not have a default value. Otherwise, the argument is optional.</p>
<p>…</p>
<p>Input object fields may be required. Much like a field may have required arguments, an input object may have required fields. An input field is required if it has a non-null type and does not have a default value. Otherwise, the input object field is optional.</p>
</blockquote>
<p>Some of the arguments being made here could be dismissed as merely semantics. In the author’s opinion, the misinformation has clearly caused real misunderstanding. Let’s break down the persistent myths.</p>
<section id="fields-are-nullable-by-default." class="level2">
<h2 class="anchored" data-anchor-id="fields-are-nullable-by-default.">Fields are <a href="https://graphql.org/learn/best-practices/#nullability">nullable by default</a>.</h2>
<blockquote class="blockquote">
<p>Most type systems which recognise “null” provide both the common type and the nullable version of that type, whereby default types do not include “null” unless explicitly declared. However, in a GraphQL type system, every field is nullable by default.</p>
</blockquote>
<p>This is true in the context of <a href="http://spec.graphql.org/October2021/#sec-Type-References">the spec</a> and the <a href="https://github.com/graphql/graphql-js#graphqljs">reference graphql-js</a> implementation. Whether it is relevant to a developer creating an API is entirely dependent on which graphql framework they are using.</p>
<ul>
<li><a href="https://docs.graphene-python.org/en/latest/types/list-and-nonnull/#nonnull">graphene-python</a>: nullable by default. Types are wrapped by a <code>NonNull</code> type or passed a <code>required=True</code> flag.</li>
<li><a href="https://strawberry.rocks/docs/general/why#why-should-you-use-strawberry">strawberry-graphql</a>: non-null by default. Following the Python convention, types must be annotated as nullable explicitly.</li>
<li><a href="https://ariadnegraphql.org">ariadne</a> and <em>every</em> schema-first framework: assuming there is a default, it would be nullable.</li>
</ul>
<p>Does the graphql schema have a “default”? In the sense that a <code>Type</code> must be annotated with a whole extra character to become <code>Type!</code>. Not in the same sense that <code>query</code> is the default operation, for example, because the operation can be omitted. There is no explicit <code>Type?</code> syntax which is being defaulted to. It is just as accurate to say there is no default in the schema; there is a syntactic binary choice.</p>
</section>
<section id="fields-should-default-to-nullable." class="level2">
<h2 class="anchored" data-anchor-id="fields-should-default-to-nullable.">Fields should <a href="https://graphql.org/learn/best-practices/#nullability">default to nullable</a>.</h2>
<blockquote class="blockquote">
<p>When designing a GraphQL schema, it’s important to keep in mind all the problems that could go wrong and if “null” is an appropriate value for a failed field. Typically it is, but occasionally, it’s not. In those cases, use non-null types to make that guarantee.</p>
</blockquote>
<p>So not whether nulls literally are the default, but the recommendation that one should default to using nullable types. This advice would be fine in theory, but in practice has reversed what is “typical” versus “occasional”. Typically, errors propagate up to an enclosing type, possibly all the way up. It is common for trivial scalars to never be null, and like any tree there are far more leaf nodes than higher nodes.</p>
<p>It is also rare to want nulls in a list. Better to omit them; even more so for input lists.</p>
<p>The standard advice is often combined with a <a href="https://www.apollographql.com/docs/technotes/TN0023-nullability/#plan-for-backward-compatibility">compatibility claim</a>.</p>
<blockquote class="blockquote">
<p>Including non-null fields and arguments in a schema makes that schema harder to evolve where a client expects a previously non-null field’s value to be provided in a response. For example, if a non-null email field on a User type is converted to a nullable field, will the clients that use that field be prepared to handle this potentially null value after the schema is updated? Similarly, if the schema changes in such a way that a client is suddenly expected to send a previously nullable argument with a request, then this may also result in a breaking change.</p>
</blockquote>
<p>Notice the common mistake: the first sentence contradicts the last with respect to arguments. Null compatibility advice applies only to outputs; the <em>opposite</em> is true for inputs. Even the staunchest pro-null advocate must concede that one should “default” to inputs being non-null.</p>
<p>A better question to ask is “what would a null in this field represent”? In an implemented API, if the field can actually be null, then there will be an answer to that question. But if the field is truly never null, then there may be no answer. You may find yourself not just <a href="https://en.wikipedia.org/wiki/Law_of_triviality">bike-shedding</a>, but counterfactual bike-shedding. How is the client supposed to “correctly” handle a response that is impossible, in a scenario that is indescribable?</p>
<p>There is no need to speculate on what a hypothetical API might do, nor to agree on a “default” behavior. Analyze how the implemented API actually behaves, and describe it accurately.</p>
</section>
<section id="optional-nullable." class="level2">
<h2 class="anchored" data-anchor-id="optional-nullable.">Optional == Nullable.</h2>
<p>GraphQL is far from the first to conflate “optional” with “nullable”, but it has elevated it to a next level. There is no context in which the quote “nullable types are always optional and non-null types are always required” is both true and not <a href="https://en.wikipedia.org/wiki/Vacuous_truth">vacuous</a>.</p>
<ul>
<li>Output field
<ul>
<li>From the client’s perspective, optional would mean the client can omit the field from the request. No, all fields are optional in that sense.</li>
<li>From the server’s perspective, optional would mean the server can omit the field from the response. No, all fields are required in that sense. Nullables may null, not omitted.</li>
</ul></li>
<li>Input field or argument
<ul>
<li>From the client’s perspective, optional would mean the client can omit the input. Yes, so they are equivalent in this case? No, an input can also be optional by having a default value, even with a non-null type. Nullable implies optional; optional does not imply nullable.</li>
<li>From the server’s perspective, optional would mean omission is equivalent to a sent null value. No, the spec clarifies that those two scenarios are <a href="http://spec.graphql.org/October2021/#sec-Input-Objects.Input-Coercion">semantically different</a>.</li>
</ul></li>
</ul>
<blockquote class="blockquote">
<p>If the value null was provided for an input object field, and the field’s type is not a non-null type, an entry in the coerced unordered map is given the value null. In other words, there is a semantic difference between the explicitly provided value null versus having not provided a value.</p>
</blockquote>
<p>So there is only one context in which the concept of “optional” has any meaning: when the client can omit the input. And being nullable is only one of two ways for an input to be optional. That makes “optional” roughly 12.5% identical to “nullable”. <code>optional == omittable != nullable</code></p>
</section>
</section>
<section id="alternatives" class="level1">
<h1>Alternatives</h1>
<p>So rather than just be a rant, let’s use this hard-fought contrarian knowledge to create better APIs.</p>
<section id="default-values-wherever-possible." class="level2">
<h2 class="anchored" data-anchor-id="default-values-wherever-possible.">Default values wherever possible.</h2>
<p>Default values are under-utilized, no surprise given <a href="https://graphql.org/learn/schema/#arguments">the introduction</a>.</p>
<blockquote class="blockquote">
<p><code>length(unit: LengthUnit = METER): Float</code></p>
<p>Arguments can be either required or optional. When an argument is optional, we can define a default value - if the unit argument is not passed, it will be set to METER by default.</p>
</blockquote>
<p>Notice the misleading phrasing combined with the nullable <code>LengthUnit</code> reinforces the false - and widespread - notion that the argument must be nullable to be optional. It would be perfectly valid for a client to send an explicit null in this example, and a good chance it is broken on the server, assuming “working” was defined. A non-null here is better in every measurable way: <code>length(unit: LengthUnit! = METER): Float</code>.</p>
<ul>
<li>the client does not have to guess what sending an explicit null would mean because it is disallowed</li>
<li>the server does not have to document or support a use case that never really existed</li>
</ul>
<p>It can not be overstated how little known default value optionality is. Once pointed out, it is impossible to not see this in APIs everywhere.</p>
<ul>
<li>the vast majority of <code>Boolean</code> inputs should be <code>Boolean! = {false,true}</code></li>
<li>the vast majority of <code>[Type!]</code> inputs should be <code>[Type!]! = []</code>. Any valid value is a valid default value, not just scalars.</li>
<li>many <code>Int</code> and <code>Float</code> inputs should be <code>Int! = 0</code> and <code>Float! = 0.0</code></li>
<li>some <code>String</code> inputs should be <code>String! = ""</code></li>
</ul>
<p>A similar dynamic has <a href="mutable-defaults.html">occurred in Python</a>. <code>None</code> is over-used as a default value, instead of a natural default. Speaking of which, Python also fell for <a href="https://docs.python.org/3/library/typing.html#typing.Optional"><code>Optional</code> equivocation</a>, but at least is trying to walk it back. <code>... | None</code> is the new preferred syntax, and the documentation is quick to point out that the <code>Optional</code> annotation does not actually mean optional.</p>
</section>
<section id="exploit-the-explicit-null-distinction." class="level2">
<h2 class="anchored" data-anchor-id="exploit-the-explicit-null-distinction.">Exploit the explicit null distinction.</h2>
<p>There are at least two scenarios where distinguishing an explicit null from omission is quite useful.</p>
<p>A partial update where null is a valid value to set, that is an unset. Often there will be a clunky <code>Boolean</code> flag to indicate “no seriously, set the null”: <code>update(name: String, setName: Boolean, ...)</code>. Instead, drop the flag and document that passing a value will update (null or otherwise), and omission will not update.</p>
<p>Another scenario is a filter where null is a valid value. It is a perfectly natural interpretation that omission means to not apply the filter, whereas an explicit null means to filter on null.</p>
<p>If this path is followed, it also becomes natural to add <code>= null</code> to inputs where there is no difference. Yes, even null is a valid default value. The point is it clearly documents to the client that there is no difference, while providing assurance that the server is implemented correctly.</p>
<p>Note many frameworks will not make it convenient to check whether an input was present. It may be necessary to check the argument map in the GraphQL info. One of the few that does is <a href="https://strawberry.rocks/docs/types/resolvers#optional-arguments">strawberry-graphql</a>, which uses <code>UNSET</code> as a sentinel. Using a sentinel when <code>None</code> is a valid value is an established pattern in Python, such as <a href="https://docs.python.org/3/library/dataclasses.html#dataclasses.MISSING"><code>dataclasses.MISSING</code></a>.</p>
</section>
<section id="use-an-optional-directive." class="level2">
<h2 class="anchored" data-anchor-id="use-an-optional-directive.">Use an <span class="citation" data-cites="optional">@optional</span> directive.</h2>
<p>There is one last case that is not well-covered. What if there is not a natural default, and no inherent meaning for null. That is, the server is being forced to declare an input as nullable when it only wants it to be optional. Using an <code>@optional</code> directive would clarify that, and remove any expectation of behavior if the client insists on sending a null.</p>
</section>
</section>
<section id="advocacy" class="level1">
<h1>Advocacy</h1>
<p>The above suggestions are in this <a href="https://github.com/graphql/graphql-spec/issues/872">GraphQL proposal</a>, and can be see implemented in the <a href="https://github.com/coady/graphique">graphique</a> project. It demonstrates fields like: <code>slice(offset: Int! = 0, length: Int = null, reverse: Boolean! = false)</code>.</p>
<p>When debating this topic, beware of undue JavaScript influence from a client perspective. For example, <code>undefined</code> is neither a GraphQL nor a <a href="https://www.json.org/json-en.html">JSON</a> concept. And all of the input points listed apply to <a href="http://spec.graphql.org/October2021/#sec-Input-Objects.Input-Coercion">input coercion</a> of variables as well.</p>


</section>

 ]]></description>
  <category>graphql</category>
  <guid>https://coady.github.io/posts/graphql-nulls.html</guid>
  <pubDate>Fri, 24 Feb 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GraphQL coroutines</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/graphql-coroutines.html</link>
  <description><![CDATA[ 






<section id="graphql-resolvers-should-have-been-coroutines." class="level1">
<h1>GraphQL resolvers should have been coroutines.</h1>
<p>This is how the GraphQL documentation <a href="https://graphql.org/learn/execution/">introduces execution</a>, as a hierarchy of resolvers:</p>
<blockquote class="blockquote">
<p>You can think of each field in a GraphQL query as a function or method of the previous type which returns the next type. In fact, this is exactly how GraphQL works. Each field on each type is backed by a function called the resolver which is provided by the GraphQL server developer. When a field is executed, the corresponding resolver is called to produce the next value.</p>
<p>If a field produces a scalar value like a string or number, then the execution completes. However if a field produces an object value then the query will contain another selection of fields which apply to that object. This continues until scalar values are reached. GraphQL queries always end at scalar values.</p>
</blockquote>
<p>There is a subtlety in the summary which is left as an exercise to the reader. The previous type must <em>prepare</em> the next types correctly such that their resolvers succeed. Specifically, all the trivial fields of the next type must be populated, not only because they may be requested, but because the next type’s resolvers invariably rely on that data.</p>
<p>It is as if parent types have a <code>pre</code> or <code>start</code> hook to setup child types. When framed that way, it becomes obvious that there is no <code>post</code> or <code>end</code> hook for a parent to finalize its result. Consider how unusual that is:</p>
<ul>
<li>test frameworks have fixture <code>setUp</code> and <code>tearDown</code></li>
<li>web frameworks have hooks around both sides of a stage in a request flow</li>
<li>inherited methods which support <code>super</code> allow code before and after the <code>super</code> call</li>
</ul>
<p>Whereas GraphQL resolvers can only provide context to child fields, with no visibility into the result. It would be like only allowing <code>super</code> as the last line in a method.</p>
<section id="example" class="level2">
<h2 class="anchored" data-anchor-id="example">Example</h2>
<p>The effect is an entire class of common problems which should be trivial. Typically - but not limited to - lists of objects which have since been deleted or for which the user is not authorized. The problem can be seen in the best practices <a href="https://graphql.org/learn/authorization/">example on authorization</a>.</p>
<blockquote class="blockquote">
<p>Authorization is a type of business logic that describes whether a given user/session/context has permission to perform an action or see a piece of data. For example:</p>
<p>“Only authors can see their drafts”</p>
</blockquote>
<p>…</p>
<div id="cell-2" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;vscode&quot;,&quot;value&quot;:{&quot;languageId&quot;:&quot;javascript&quot;}}">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span>Authorization logic lives inside postRepository</span>
<span id="cb1-2">var postRepository <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> require(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'postRepository'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-3"></span>
<span id="cb1-4">var postType <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> new GraphQLObjectType({</span>
<span id="cb1-5">  name: ‘Post’,</span>
<span id="cb1-6">  fields: {</span>
<span id="cb1-7">    body: {</span>
<span id="cb1-8">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>: GraphQLString,</span>
<span id="cb1-9">      resolve: (post, args, context, { rootValue }) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> {</span>
<span id="cb1-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> postRepository.getBody(context.user, post)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-11">      }</span>
<span id="cb1-12">    }</span>
<span id="cb1-13">  }</span>
<span id="cb1-14">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</div>
<p>The incomplete example does <em>not</em> implement “only authors can see their drafts”. It implements “only authors can see the <code>body</code> field of a draft”. But the user would still know the post exists and see all metadata which is not protected. “Drafts” being plural and all, a parent field with a list of <code>posts</code> is missing from the example. Surely the preferred solution would be to not return the unauthorized post in the list at all.</p>
<p>The same problem exists if the post should be hidden for any reason, including deletion. It cannot be overstated how common a problem this is in real world APIs, and GraphQL offers no solution.</p>
<p>Well, as constructed. The workaround is to abandon the premise of the example and push the authorization logic up to the <code>posts</code> field. But even that fails to address race conditions, which are particularly relevant for deletions.</p>
<p>Interestingly, it would also be more efficient if the query which determined the list of posts were “correct” in the first place. This relates to a previous article <a href="graphql-orm.html">GraphQL is the new ORM</a>, which focused on performance. Ultimately this is the same issue: <strong>the elegance of single-purpose resolvers fails when context has been lost, and that failure is especially common and noticeable when lists are involved</strong>.</p>
</section>
<section id="solution" class="level2">
<h2 class="anchored" data-anchor-id="solution">Solution</h2>
<p>A general solution would be to allow resolvers to be coroutines, or equivalently to allow a <code>finalize</code> resolver. Here is an example implemented in <a href="https://github.com/graphql-python/graphql-core">graphql-core</a>:</p>
<div id="cell-4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>execution<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>execute.py</span>
<span id="cb2-2"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+++</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>execution<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>execute.py</span>
<span id="cb2-3"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">546</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">546</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> ExecutionContext:</span>
<span id="cb2-4">             completed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.complete_value(</span>
<span id="cb2-5">                 return_type, field_nodes, info, path, result</span>
<span id="cb2-6">             )</span>
<span id="cb2-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> field_def.finalize <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb2-8"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>                completed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> field_def.finalize(completed, info, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args)</span>
<span id="cb2-9">             <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.is_awaitable(completed):</span>
<span id="cb2-10">                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># noinspection PyShadowingNames</span></span>
<span id="cb2-11">                 <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">async</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> await_completed() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Any:</span>
<span id="cb2-12">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span>git a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>definition.py b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>definition.py</span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>definition.py</span>
<span id="cb2-15"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+++</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>graphql<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>definition.py</span>
<span id="cb2-16"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">471</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">471</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> GraphQLField:</span>
<span id="cb2-17">     deprecation_reason: Optional[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>]</span>
<span id="cb2-18">     extensions: Dict[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Any]</span>
<span id="cb2-19">     ast_node: Optional[FieldDefinitionNode]</span>
<span id="cb2-20"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>    finalize: Optional[GraphQLFieldResolver]</span>
<span id="cb2-21"> </span>
<span id="cb2-22">     <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(</span>
<span id="cb2-23">         <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb2-24"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">482</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">483</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> GraphQLField:</span>
<span id="cb2-25">         deprecation_reason: Optional[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb2-26">         extensions: Optional[Dict[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Any]] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb2-27">         ast_node: Optional[FieldDefinitionNode] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb2-28"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>        finalize: Optional[GraphQLFieldResolver] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb2-29">     ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb2-30">         <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> args:</span>
<span id="cb2-31">             args <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-32"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">502</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@@</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> GraphQLField:</span>
<span id="cb2-33">         <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.deprecation_reason <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> deprecation_reason</span>
<span id="cb2-34">         <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.extensions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extensions <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> {}</span>
<span id="cb2-35">         <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ast_node <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ast_node</span>
<span id="cb2-36"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.finalize <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> finalize</span>
<span id="cb2-37"> </span>
<span id="cb2-38">     <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__repr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb2-39">         <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"&lt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__class__</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!r}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">&gt;"</span></span></code></pre></div></div>
</div>
<p>With that minor extension, fields can supply a <code>finalize</code> resolver in addition to the usual one.</p>
<div id="cell-6" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> graphql <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> (</span>
<span id="cb3-3">    GraphQLField,</span>
<span id="cb3-4">    GraphQLInt,</span>
<span id="cb3-5">    GraphQLList,</span>
<span id="cb3-6">    GraphQLNonNull,</span>
<span id="cb3-7">    GraphQLObjectType,</span>
<span id="cb3-8">    GraphQLSchema,</span>
<span id="cb3-9">    GraphQLString,</span>
<span id="cb3-10">    graphql_sync,</span>
<span id="cb3-11">    print_schema,</span>
<span id="cb3-12">)</span>
<span id="cb3-13"></span>
<span id="cb3-14">post_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first"</span>}</span>
<span id="cb3-15"></span>
<span id="cb3-16"></span>
<span id="cb3-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="cb3-18"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Post:</span>
<span id="cb3-19">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb3-20"></span>
<span id="cb3-21">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> body(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, info) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb3-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> post_data.get(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>)</span>
<span id="cb3-23"></span>
<span id="cb3-24"></span>
<span id="cb3-25">postType <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GraphQLObjectType(</span>
<span id="cb3-26">    name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Post"</span>,</span>
<span id="cb3-27">    fields<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb3-28">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: GraphQLNonNull(GraphQLInt),</span>
<span id="cb3-29">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"body"</span>: GraphQLField(GraphQLString, resolve<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Post.body),</span>
<span id="cb3-30">    },</span>
<span id="cb3-31">)</span>
<span id="cb3-32"></span>
<span id="cb3-33">postsField <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GraphQLField(</span>
<span id="cb3-34">    GraphQLNonNull(GraphQLList(GraphQLNonNull(postType))),</span>
<span id="cb3-35">    resolve<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>_: [Post(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), Post(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)],</span>
<span id="cb3-36">    finalize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> objs, _: [obj <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> obj <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> objs <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> obj[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"body"</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>],</span>
<span id="cb3-37">)</span>
<span id="cb3-38"></span>
<span id="cb3-39">schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GraphQLSchema(</span>
<span id="cb3-40">    query<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>GraphQLObjectType(name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Query"</span>, fields<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"posts"</span>: postsField})</span>
<span id="cb3-41">)</span>
<span id="cb3-42"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(print_schema(schema))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>type Query {
  posts: [Post!]!
}

type Post {
  id: Int!
  body: String
}</code></pre>
</div>
</div>
<div id="cell-7" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">source <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{ posts { id body } }"</span></span>
<span id="cb5-2">graphql_sync(schema, source)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>ExecutionResult(data={'posts': [{'id': 1, 'body': 'first'}]}, errors=None)</code></pre>
</div>
</div>
</section>
<section id="addendum" class="level2">
<h2 class="anchored" data-anchor-id="addendum">Addendum</h2>
<p>In Python, this could be implemented as a generator-based coroutine. Similar to <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager">contextlib.contextmanager</a> or <a href="https://docs.pytest.org/en/7.2.x/how-to/fixtures.html#yield-fixtures-recommended">pytest fixtures</a>, the generator would yield types, receive the result maps, and yield one more final result.</p>
<div id="cell-9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> resolve(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>_):</span>
<span id="cb7-2">    objs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> [Post(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), Post(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)]</span>
<span id="cb7-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> [obj <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> obj <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> objs <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> obj[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"body"</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]</span></code></pre></div></div>
</div>
<p>But there are some obstacles to that approach. The result data is in map (<code>dict</code>) form, not the domain types, so the code is not necessarily more readable. Additionally, generators can already be used to implement list types (whether intentional or not); <code>graphql-core</code> simply iterates the result. There would need to be another mechanism to distinguish a true coroutine from a regular generator.</p>
<p>Speaking of domain types, notice how convenient and readable using a <code>dataclass</code> is, and how redundant the GraphQL type definition is. In <a href="https://strawberry.rocks">strawberry-graphql</a>, the schema is automatically derived from the domain types. The example would be simply:</p>
<div id="cell-11" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.type</span></span>
<span id="cb8-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Post:</span>
<span id="cb8-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb8-4"></span>
<span id="cb8-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strawberry.field</span></span>
<span id="cb8-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> body(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb8-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> post_data.get(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>)</span></code></pre></div></div>
</div>


</section>
</section>

 ]]></description>
  <category>graphql</category>
  <guid>https://coady.github.io/posts/graphql-coroutines.html</guid>
  <pubDate>Mon, 20 Feb 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Random Selection</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/random-selection.html</link>
  <description><![CDATA[ 






<p>Random selection utilities used to be common in interviews. Less so in Python circles because of the builtin <code>random</code> module. Still advanced examples may come up. First is a generalization of <code>shuffle</code> and <code>sample</code>.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> shuffled(iterable):</span>
<span id="cb1-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate values in random order for any iterable.</span></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    </span></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Faster than `random.shuffle` if not all values are required.</span></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    More flexible than `random.sample` if the desired number is unknown a priori.</span></span>
<span id="cb1-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-10">    values <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(iterable)</span>
<span id="cb1-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> values:</span>
<span id="cb1-12">        index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.randrange(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(values))</span>
<span id="cb1-13">        values[index], values[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> values[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], values[index]</span>
<span id="cb1-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> values.pop()</span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.islice(shuffled(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>[9, 7, 5, 4, 6]</code></pre>
</div>
</div>
<p>Next up is a random sample in a single pass, e.g., if the data is being read from a large file. The solution requires <a href="https://en.wikipedia.org/wiki/Mathematical_induction">mathematical induction</a>:</p>
<ul>
<li>each Nth element has a fair chance of being selected</li>
<li>each previously selected element has a fair chance of being removed</li>
</ul>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sample(iterable, k):</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return a random sample from any iterable in a single pass.</span></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    </span></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    More memory efficient than `random.sample`.</span></span>
<span id="cb3-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb3-6">    it <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(iterable)</span>
<span id="cb3-7">    selection <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.islice(it, k))</span>
<span id="cb3-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># error handling and shuffling are consistent with random.sample</span></span>
<span id="cb3-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(selection):</span>
<span id="cb3-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample larger than population"</span>)</span>
<span id="cb3-11">    random.shuffle(selection)</span>
<span id="cb3-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> count, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(it, k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb3-13">        index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.randrange(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, count)</span>
<span id="cb3-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(selection):</span>
<span id="cb3-15">            selection[index] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> value</span>
<span id="cb3-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> selection</span>
<span id="cb3-17"></span>
<span id="cb3-18">sample(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[1, 2, 6, 3, 8]</code></pre>
</div>
</div>



 ]]></description>
  <category>interviews</category>
  <guid>https://coady.github.io/posts/random-selection.html</guid>
  <pubDate>Mon, 02 Jan 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Primes</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/primes.html</link>
  <description><![CDATA[ 






<p>An old interview challenge is to generate prime numbers or check if a number is prime. No advanced mathematics needed, just variants on the <a href="https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes">Sieve of Eratosthenes</a>. Starting with a basic prime checker.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> isprime(n):</span>
<span id="cb1-2">    divs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> d <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> divs)</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time isprime(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 83 µs, sys: 1e+03 ns, total: 84 µs
Wall time: 85.1 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>True</code></pre>
</div>
</div>
<p>A common optimization is to skip even numbers.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> isprime(n):</span>
<span id="cb4-2">    divs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb4-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> d <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> divs)</span>
<span id="cb4-4"></span>
<span id="cb4-5"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time isprime(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 43 µs, sys: 0 ns, total: 43 µs
Wall time: 46.3 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>True</code></pre>
</div>
</div>
<p>Brief digression on that optimization. There’s nothing special about removing multiples of 2; removing multiples is the whole point. The <code>step</code> scalar could instead be thought of as a cycle: <code>itertools.accumulate(itertools.repeat(2))</code>. So removing multiples of 3 would remove every third step: <code>itertools.accumulate(itertools.cycle([2, 4]))</code>.</p>
<p>Or the equivalent could be done with slicing.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> isprime(n):</span>
<span id="cb7-4">    divs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb7-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> d <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.chain(divs[::<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], divs[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>::<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]))</span>
<span id="cb7-6"></span>
<span id="cb7-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time isprime(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 42 µs, sys: 1 µs, total: 43 µs
Wall time: 44.1 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>True</code></pre>
</div>
</div>
<p>The catch is the cycles grow exponentially with diminishing returns on each successive number.</p>
<p>Onto prime generation, while keeping the odds-only optimization. Typically it’s requested to generate the first <code>N</code> primes, or up to some value. But that’s easily generalized with <code>itertools.islice</code> and <code>itertools.takewhile</code>. A more Pythonic approach is an unbounded generator.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> primes():</span>
<span id="cb10-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb10-3">    ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb10-5">        prime <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(ints)</span>
<span id="cb10-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> prime</span>
<span id="cb10-7">        ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (n <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ints <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> prime)</span>
<span id="cb10-8"></span>
<span id="cb10-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.islice(primes(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>[2, 3, 5, 7, 9, 11, 13, 15, 17, 19]</code></pre>
</div>
</div>
<p>Elegant, but doesn’t work. The problem is the scoping of <code>prime</code>, which is being used in the generator expression but also modified in the loop. Instead it can be replaced with a <code>filter</code> on a partially bound function, but unfortunately <code>functools.partial</code> only binds left arguments and <code>rmod</code> is needed here. One alternative is to use bound methods as a first-class function, even dunder methods.</p>
<div id="cell-10" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> primes():</span>
<span id="cb12-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb12-3">    ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb12-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb12-5">        prime <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(ints)</span>
<span id="cb12-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> prime</span>
<span id="cb12-7">        ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(prime.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__rmod__</span>, ints)</span>
<span id="cb12-8"></span>
<span id="cb12-9"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(itertools.islice(primes(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 30.7 ms, sys: 1.82 ms, total: 32.5 ms
Wall time: 32 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>7927</code></pre>
</div>
</div>
<p>Elegant, but slow and could overflow the stack. A more traditional approach would use the same checking logic as <code>isprime</code>, but also cache the primes so as to not duplicate divisors.</p>
<div id="cell-12" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> primes():</span>
<span id="cb15-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb15-3">    primes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb15-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb15-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> p <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.takewhile(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>).<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__ge__</span>, primes)):</span>
<span id="cb15-6">            primes.append(n)</span>
<span id="cb15-7">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb15-8"></span>
<span id="cb15-9"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(itertools.islice(primes(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 5.49 ms, sys: 423 µs, total: 5.92 ms
Wall time: 5.8 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>7927</code></pre>
</div>
</div>
<p>Onto interface design. The primes are being stored anyway, so it would be nice if they were re-iterable. A generator can be written as a class with <code>__iter__</code> and <code>__next__</code>, but an under-appreciated feature is that <code>__iter__</code> itself can be a generator. And now that it’s a class, <code>isprime</code> can be expressed as <code>in</code> while also benefiting from the cache.</p>
<div id="cell-14" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Primes:</span>
<span id="cb18-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb18-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb18-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb18-5">    </span>
<span id="cb18-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb18-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache</span>
<span id="cb18-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ints:</span>
<span id="cb18-9">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>:</span>
<span id="cb18-10">                <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache.append(n)</span>
<span id="cb18-11">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb18-12"></span>
<span id="cb18-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__contains__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n):</span>
<span id="cb18-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> p <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.takewhile(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>).<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__ge__</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>))</span>
<span id="cb18-15"></span>
<span id="cb18-16">primes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Primes()</span>
<span id="cb18-17"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(itertools.islice(primes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 7.89 ms, sys: 483 µs, total: 8.37 ms
Wall time: 8 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>7927</code></pre>
</div>
</div>
<div id="cell-15" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> primes</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 34 µs, sys: 0 ns, total: 34 µs
Wall time: 37 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>True</code></pre>
</div>
</div>
<p>There’s a hybrid approach though, that’s faster and nearly as simple as the above sieves. Instead of doing repeated divisions, keep track of each found prime along with the next multiple that it would eliminate. The inner loop is then optimized because it only needs to account for collisions.</p>
<div id="cell-17" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> primes():</span>
<span id="cb24-2">    multiples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb24-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb24-4">        prime <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> multiples.pop(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb24-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> prime:</span>
<span id="cb24-6">            prime <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n</span>
<span id="cb24-7">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb24-8">        key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> prime</span>
<span id="cb24-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> multiples:</span>
<span id="cb24-10">            key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> prime</span>
<span id="cb24-11">        multiples[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prime</span>
<span id="cb24-12"></span>
<span id="cb24-13"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(itertools.islice(primes(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 2.59 ms, sys: 103 µs, total: 2.69 ms
Wall time: 2.7 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>7927</code></pre>
</div>
</div>
<p>Now to add back the odds-only optimization, the step scalar needs to be double the prime number. Another way to reduce collisions is to recognize that each new prime is irrelevant until its square value is reached.</p>
<div id="cell-19" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> primes():</span>
<span id="cb27-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb27-3">    multiples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb27-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb27-5">        step <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> multiples.pop(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb27-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> step:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># composite</span></span>
<span id="cb27-7">            key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> step</span>
<span id="cb27-8">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> multiples:</span>
<span id="cb27-9">                key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> step</span>
<span id="cb27-10">            multiples[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> step</span>
<span id="cb27-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># prime</span></span>
<span id="cb27-12">            multiples[n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb27-13">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb27-14"></span>
<span id="cb27-15"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(itertools.islice(primes(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 1.37 ms, sys: 5 µs, total: 1.38 ms
Wall time: 1.38 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>7927</code></pre>
</div>
</div>
<p>And finally let’s add back the caching. Yielding a clean interface, an efficient implementation for all use cases, and still relatively simple.</p>
<div id="cell-21" class="cell" data-execution_count="11">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Primes:</span>
<span id="cb30-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb30-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ints <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb30-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb30-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.multiples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb30-6">    </span>
<span id="cb30-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb30-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache</span>
<span id="cb30-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ints:</span>
<span id="cb30-10">            step <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.multiples.pop(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb30-11">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> step:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># composite</span></span>
<span id="cb30-12">                key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> step</span>
<span id="cb30-13">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.multiples:</span>
<span id="cb30-14">                    key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> step</span>
<span id="cb30-15">                <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.multiples[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> step</span>
<span id="cb30-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># prime</span></span>
<span id="cb30-17">                <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.multiples[n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb30-18">                <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.cache.append(n)</span>
<span id="cb30-19">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb30-20"></span>
<span id="cb30-21">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__contains__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n):</span>
<span id="cb30-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> p <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.takewhile(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>).<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__ge__</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>))</span>
<span id="cb30-23"></span>
<span id="cb30-24">primes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Primes()</span>
<span id="cb30-25"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> primes</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 242 µs, sys: 0 ns, total: 242 µs
Wall time: 245 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="11">
<pre><code>True</code></pre>
</div>
</div>
<div id="cell-22" class="cell" data-execution_count="12">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_003</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> primes</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 40 µs, sys: 0 ns, total: 40 µs
Wall time: 43.2 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="12">
<pre><code>True</code></pre>
</div>
</div>



 ]]></description>
  <category>interviews</category>
  <guid>https://coady.github.io/posts/primes.html</guid>
  <pubDate>Sat, 10 Jul 2021 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Hardest Logic Puzzle Ever</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/hardest-logic-puzzle-ever.html</link>
  <description><![CDATA[ 






<section id="how-to-solve-the-hardest-logic-puzzle-ever-programmatically." class="level1">
<h1>How to solve the <a href="https://en.wikipedia.org/wiki/The_Hardest_Logic_Puzzle_Ever">Hardest Logic Puzzle Ever</a> programmatically.</h1>
<blockquote class="blockquote">
<p>Three gods A, B, and C are called, in no particular order, True, False, and Random. True always speaks truly, False always speaks falsely, but whether Random speaks truly or falsely is a completely random matter. Your task is to determine the identities of A, B, and C by asking three yes-no questions; each question must be put to exactly one god. The gods understand English, but will answer all questions in their own language, in which the words for yes and no are <code>da</code> and <code>ja</code>, in some order. You do not know which word means which.</p>
</blockquote>
<p>With 3 binary questions, it’s possible to distinguish <img src="https://latex.codecogs.com/png.latex?2%5E3%20=%208"> scenarios. And there are <img src="https://latex.codecogs.com/png.latex?3!%20=%206"> possibilities. Note that means it’s impossible to additionally identify what <code>da</code> and <code>ja</code> mean, as that would be <img src="https://latex.codecogs.com/png.latex?3!%20*%202%20=%2012"> possibilities.</p>
<p>As always, start with modeling the data. We need a ternary enumeration for the god identifiers. It’s almost a boolean anyway, so let’s use <code>None</code> to indicate neither, i.e., Random. To represent the identities, a mapping from names to ids would be natural. But the mapping has to be one-to-one and onto, and using an immutable key is convenient, so an implicitly ordered tuple of names is also a valid choice. Here a named tuple represents the “state” of the world .</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> NamedTuple</span>
<span id="cb1-3"></span>
<span id="cb1-4">IDS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb1-5">NAMES <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ABC'</span></span>
<span id="cb1-6">WORDS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'da'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ja'</span>)</span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> State(NamedTuple):</span>
<span id="cb1-9">    names: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># order corresponds to IDS</span></span>
<span id="cb1-10">    yes: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-11"></span>
<span id="cb1-12">STATES <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.starmap(State, itertools.product(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join, itertools.permutations(NAMES)), WORDS)))</span>
<span id="cb1-13">STATES</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>[State(names='ABC', yes='da'),
 State(names='ABC', yes='ja'),
 State(names='ACB', yes='da'),
 State(names='ACB', yes='ja'),
 State(names='BAC', yes='da'),
 State(names='BAC', yes='ja'),
 State(names='BCA', yes='da'),
 State(names='BCA', yes='ja'),
 State(names='CAB', yes='da'),
 State(names='CAB', yes='ja'),
 State(names='CBA', yes='da'),
 State(names='CBA', yes='ja')]</code></pre>
</div>
</div>
<p>Now to model asking a question. A typical approach would take input parameters relevant to the question, such as asking a god which one they are. And the current reality would be need to be encapsulated to answer the question.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>: State, name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Ask `name`: are you `id`?"""</span></span></code></pre></div></div>
</div>
<p>The problem with that approach is Random’s answer would have to be modeled as actually random, which would require running many simulations. Since this is a logic puzzle, it’s easier to model Random’s answer as non-deterministic, i.e., could answer either way. The question will take as input the current set of possible states, splitting the states into two groups corresponding to answers da or ja. This function will be used in a search algorithm anyway, so it’s effectively participating in the search.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, states: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>:</span>
<span id="cb4-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Ask `name`: are you `id`? and return mapping of answers to possible states."""</span></span>
<span id="cb4-3">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {word: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> word <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> WORDS}</span>
<span id="cb4-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> states:</span>
<span id="cb4-5">        identity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> IDS[state.names.index(name)]</span>
<span id="cb4-6">        truth <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> identity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span></span>
<span id="cb4-7">        words <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(WORDS, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>state.yes.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__eq__</span>)</span>
<span id="cb4-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> identity <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb4-9">            groups[words[truth]].add(state)</span>
<span id="cb4-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> identity <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb4-11">            groups[words[<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> truth]].add(state)</span>
<span id="cb4-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> groups</span>
<span id="cb4-13"></span>
<span id="cb4-14">ask(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, STATES)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>{'da': {State(names='ABC', yes='da'),
  State(names='ACB', yes='da'),
  State(names='BAC', yes='ja'),
  State(names='BCA', yes='da'),
  State(names='BCA', yes='ja'),
  State(names='CAB', yes='ja'),
  State(names='CBA', yes='da'),
  State(names='CBA', yes='ja')},
 'ja': {State(names='ABC', yes='ja'),
  State(names='ACB', yes='ja'),
  State(names='BAC', yes='da'),
  State(names='BCA', yes='da'),
  State(names='BCA', yes='ja'),
  State(names='CAB', yes='da'),
  State(names='CBA', yes='da'),
  State(names='CBA', yes='ja')}}</code></pre>
</div>
</div>
<p>To determine if a question is making progress, we need to look at the set of names returned for each answer. A valid solution would need to output sets of at most size <img src="https://latex.codecogs.com/png.latex?2%5E2%20=%204"> on the first question in order to proceed.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> IDS:</span>
<span id="cb6-2">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, STATES)</span>
<span id="cb6-3">    identities <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{names <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> names, _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> group} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups.values()]</span>
<span id="cb6-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>identities)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>False {'BAC', 'CBA', 'CAB', 'ABC', 'ACB', 'BCA'} {'CAB', 'CBA', 'BAC', 'ABC', 'ACB', 'BCA'}
True {'CAB', 'CBA', 'BAC', 'ABC', 'ACB', 'BCA'} {'BAC', 'CBA', 'CAB', 'ABC', 'ACB', 'BCA'}
None {'BAC', 'CBA', 'CAB', 'ABC', 'ACB', 'BCA'} {'CAB', 'CBA', 'BAC', 'ABC', 'ACB', 'BCA'}</code></pre>
</div>
</div>
<p>So that question made no progress. Unsurprising given that we don’t know which god is “Random”. Here one could resort to heuristics and increasingly convoluted questions.</p>
<p>Let’s do the opposite: write the most general question possible and automate the search. Any question can be modeled by asking whether any of a given set of states is accurate.</p>
<div id="cell-10" class="cell" data-tags="[]" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, include: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, exclude: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>:</span>
<span id="cb8-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Ask `name`: are we in any of `include` states? and return mapping of answers to possible states."""</span></span>
<span id="cb8-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> include.isdisjoint(exclude)</span>
<span id="cb8-4">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {word: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> word <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> WORDS}</span>
<span id="cb8-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> include <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> exclude:</span>
<span id="cb8-6">        identity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> IDS[state.names.index(name)]</span>
<span id="cb8-7">        truth <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> include</span>
<span id="cb8-8">        words <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(WORDS, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>state.yes.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__eq__</span>)</span>
<span id="cb8-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> identity <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb8-10">            groups[words[truth]].add(state)</span>
<span id="cb8-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> identity <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb8-12">            groups[words[<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> truth]].add(state)</span>
<span id="cb8-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> groups</span>
<span id="cb8-14"></span>
<span id="cb8-15">include <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES[:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(STATES) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb8-16">ask(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>, include, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> include)        </span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>{'da': {State(names='ABC', yes='ja'),
  State(names='ACB', yes='ja'),
  State(names='BAC', yes='da'),
  State(names='BCA', yes='da'),
  State(names='BCA', yes='ja'),
  State(names='CAB', yes='ja'),
  State(names='CBA', yes='da'),
  State(names='CBA', yes='ja')},
 'ja': {State(names='ABC', yes='da'),
  State(names='ACB', yes='da'),
  State(names='BAC', yes='ja'),
  State(names='BCA', yes='da'),
  State(names='BCA', yes='ja'),
  State(names='CAB', yes='da'),
  State(names='CBA', yes='da'),
  State(names='CBA', yes='ja')}}</code></pre>
</div>
</div>
<p>With that, the <a href="https://en.wikipedia.org/wiki/Power_set">power set</a> of all possible combinations can be searched.</p>
<div id="cell-12" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> powerset(states: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>):</span>
<span id="cb10-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate all possible subsets."""</span></span>
<span id="cb10-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(states) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb10-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, itertools.combinations(states, r))</span>
<span id="cb10-5"></span>
<span id="cb10-6">count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb10-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> states <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> powerset(STATES):</span>
<span id="cb10-8">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>, states, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> states)</span>
<span id="cb10-9">    identities <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{names <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> names, _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> group} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups.values()]</span>
<span id="cb10-10">    count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>, identities)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb10-11">count</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>96</code></pre>
</div>
</div>
<p>So there are many potential solutions. Onto automating the search.</p>
<div id="cell-14" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> search(states: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>):</span>
<span id="cb12-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Recursively ask all possible questions until a solution is found."""</span></span>
<span id="cb12-3">    identities <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {names <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> names, _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> states}</span>
<span id="cb12-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(identities) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># solved</span></span>
<span id="cb12-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> identities.pop()</span>
<span id="cb12-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> count <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(identities) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> count):  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># impossible</span></span>
<span id="cb12-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb12-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, subset <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.product(NAMES, powerset(states)):</span>
<span id="cb12-9">        groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask(name, subset, states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> subset)</span>
<span id="cb12-10">        solutions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [search(group, count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups.values()]</span>
<span id="cb12-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(solutions):</span>
<span id="cb12-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> name, subset, solutions</span>
<span id="cb12-13"></span>
<span id="cb12-14">search(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>'ABC'</code></pre>
</div>
</div>
<div id="cell-15" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">search(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>('A',
 {State(names='ABC', yes='da'), State(names='ACB', yes='ja')},
 ['ACB', 'ABC'])</code></pre>
</div>
</div>
<div id="cell-16" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">search(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>('A',
 {State(names='ABC', yes='da'), State(names='ACB', yes='ja')},
 [('A', {State(names='ACB', yes='da')}, ['BAC', 'ACB']),
  ('A', {State(names='ABC', yes='ja')}, ['ABC', 'BAC'])])</code></pre>
</div>
</div>
<p>So far, so good. The output is binary tree specifying the addressed god and the states asked about at each node.</p>
<p>The sub-problems are solving a sufficient number of cases. It’s no surpise that there should be solutions asking “A” first since it can’t matter who gets the first question. Now for the real solution.</p>
<div id="cell-18" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time search(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(STATES))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 1.29 s, sys: 10.8 ms, total: 1.3 s
Wall time: 1.3 s</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>('A',
 {State(names='ABC', yes='da'),
  State(names='ACB', yes='ja'),
  State(names='BAC', yes='ja'),
  State(names='CAB', yes='da')},
 [('C',
   {State(names='ACB', yes='ja'),
    State(names='BCA', yes='da'),
    State(names='CAB', yes='da'),
    State(names='CBA', yes='ja')},
   [('B',
     {State(names='BCA', yes='ja'), State(names='CBA', yes='ja')},
     ['BCA', 'CBA']),
    ('A',
     {State(names='ACB', yes='da'), State(names='CAB', yes='da')},
     ['CAB', 'ACB'])]),
  ('B',
   {State(names='ABC', yes='da'),
    State(names='BAC', yes='da'),
    State(names='BCA', yes='ja'),
    State(names='CBA', yes='ja')},
   [('B',
     {State(names='ABC', yes='da'), State(names='BCA', yes='da')},
     ['ABC', 'BCA']),
    ('B',
     {State(names='BAC', yes='ja'), State(names='CBA', yes='ja')},
     ['BAC', 'CBA'])])])</code></pre>
</div>
</div>
<p>The puzzle is solved. Can it be simplified? Depends on your point of view.</p>
<p><a href="https://en.wikipedia.org/wiki/The_Hardest_Logic_Puzzle_Ever#The_solution">Canonical solutions</a> introduce <a href="https://en.wikipedia.org/wiki/Logical_biconditional">biconditionals</a> or <a href="https://en.wikipedia.org/wiki/Counterfactual_conditional">conterfactuals</a> in an attempt to collapse the output possibilities. This is ultimately hopeless though, as the solution is a binary search tree regardless. Is asking a question of the form “If I asked you …, would just say ja” actually clearer than asking “Are we in any of these possibilities: …”?</p>
<p>Nonetheless patterns do emerge:</p>
<ul>
<li>The first question revolves around ruling out “Random”.</li>
<li>Subsequent questions address non-“Random” gods.</li>
</ul>
<p>The random behavior adds true complexity to the algorithm, whereas the the boolean encoding adds arbitrary complications.</p>


</section>

 ]]></description>
  <category>puzzles</category>
  <guid>https://coady.github.io/posts/hardest-logic-puzzle-ever.html</guid>
  <pubDate>Fri, 01 Jan 2021 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GraphQL - ORM</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/graphql-orm.html</link>
  <description><![CDATA[ 






<section id="graphql-is-the-new-orm." class="level1">
<h1>GraphQL is the new ORM.</h1>
<p><a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> and <a href="https://en.wikipedia.org/wiki/Object-relational_mapping">ORMs</a> are both infamous for:</p>
<ul>
<li>over-fetching: fetching more data than is needed per request</li>
<li>under-fetching: fetching less data than is needed, requiring multiple requests</li>
<li>select N+1 problem: under-fetching applied to multiple associated objects</li>
</ul>
<p><a href="https://en.wikipedia.org/wiki/GraphQL">GraphQL</a> aims to overcome REST’s shortcomings through a flexible query language, and succeeds in doing so on the client side. But on the server side, GraphQL resolvers have effectively recreated the same over- and under- fetching problems that have long plagued ORMs. The fact that ORMs remain popular despite of their inefficiency is a testament to the benefits of having in-memory objects behave consistently. There is no such trade-off for server-side GraphQL, where the only point of the objects is to be immediately serialized.</p>
<p>The so-called <a href="https://engineering.shopify.com/blogs/engineering/solving-the-n-1-problem-for-graphql-through-batching">N+1 problem</a> is generally acknowledged in the GraphQL community, but this article will argue only the symptoms are being addressed with workarounds like <a href="https://github.com/graphql/dataloader">dataloader</a>.</p>
<section id="example" class="level2">
<h2 class="anchored" data-anchor-id="example">Example</h2>
<p>The problems can be seen immediately in GraphQL’s own introductory <a href="https://graphql.org/learn/execution/#root-fields-resolvers">resolver example</a>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode javascript code-with-copy"><code class="sourceCode javascript"><span id="cb1-1">Query<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">human</span>(obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> info) {</span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">db</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">loadHumanByID</span>(args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(</span>
<span id="cb1-4">      userData <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Human</span>(userData)</span>
<span id="cb1-5">    )</span>
<span id="cb1-6">  }</span>
<span id="cb1-7">}</span>
<span id="cb1-8"></span>
<span id="cb1-9">Human<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span>(obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> info) {</span>
<span id="cb1-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name</span></span>
<span id="cb1-12">  }</span>
<span id="cb1-13">}</span></code></pre></div></div>
<p>What makes the <code>name</code> resolver trivial? It’s pre-fetched by <code>loadHumanByID</code>, whose only parameter is <code>id</code>, so it’s clearly unaware of whether <code>name</code> has been requested. What if the requested field was a nested object, or a json field, or just a large text blob? Then one would clearly be directed towards using a non-trivial resolver which fetches the field on demand. Of course, but then whatever work is common in the human <code>id</code> lookup is duplicated.</p>
<p>This is by no means specific to SQL or relational databases, but SQL is a convenient lingua franca of databases to demonstrate the inefficiency. The choices are:</p>
<ul>
<li><code>SELECT * FROM human WHERE id = ?</code></li>
<li><code>SELECT field FROM human WHERE id = ?</code> repeated for each “expensive” field</li>
</ul>
<p>Even in the simplest possible example, over-fetching has already occurred, and the only proposed workaround is under-fetching. The single query we want is:</p>
<ul>
<li><code>SELECT f1, f2, ... FROM human WHERE id = ?</code> for requested fields</li>
</ul>
<p>In other words, exactly what happens with ORMs, except even ORMs typically offer an option of requesting a subset of fields. Naturally the problem gets worse with list fields.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode javascript code-with-copy"><code class="sourceCode javascript"><span id="cb2-1">Human<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb2-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">appearsIn</span>(obj) {</span>
<span id="cb2-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">appearsIn</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// returns [ 4, 5, 6 ]</span></span>
<span id="cb2-4">  }</span>
<span id="cb2-5">}</span>
<span id="cb2-6"></span>
<span id="cb2-7">Human<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb2-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">starships</span>(obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> info) {</span>
<span id="cb2-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> obj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">starshipIDs</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(</span>
<span id="cb2-10">      id <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">db</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">loadStarshipByID</span>(id)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(</span>
<span id="cb2-11">        shipData <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Starship</span>(shipData)</span>
<span id="cb2-12">      )</span>
<span id="cb2-13">    )</span>
<span id="cb2-14">  }</span>
<span id="cb2-15">}</span></code></pre></div></div>
<p>Now there are two sets of associate keys (<code>.appearsIn</code> and <code>.starshipIDs</code>) that have been over-fetched. Nonetheless <code>starships</code> is under-fetched as well. The <code>starships</code> resolver is neither the most efficient nor the simplest way of resolving this field:</p>
<ul>
<li>fetch all the data by human <code>id</code> in the <code>starships</code> resolver</li>
<li>fetch all the data in bulk by <code>starshipIDs</code></li>
<li>push the resolution down to the <code>Starship</code> layer if forced to fetch one at a time</li>
</ul>
<p>The example implementation seems to be going out of its way to showcase JavaScript promises. And the assumptions being made about the underlying data store are unusual:</p>
<ol type="1">
<li>The data is relational in nature.</li>
<li>Associative keys have neglible cost to pre-fetch.</li>
<li>But joins are not available.</li>
<li>And neither are <code>primary key in</code> queries.</li>
</ol>
</section>
<section id="workaround" class="level2">
<h2 class="anchored" data-anchor-id="workaround">Workaround</h2>
<p>From GraphQL’s <a href="https://graphql.org/learn/best-practices/#server-side-batching-caching">best practices</a></p>
<blockquote class="blockquote">
<p>GraphQL is designed in a way that allows you to write clean code on the server, where every field on every type has a focused single-purpose function for resolving that value. However without additional consideration, a naive GraphQL service could be very “chatty” or repeatedly load data from your databases.</p>
</blockquote>
<blockquote class="blockquote">
<p>This is commonly solved by a batching technique, where multiple requests for data from a backend are collected over a short period of time and then dispatched in a single request to an underlying database or microservice by using a tool like Facebook’s DataLoader.</p>
</blockquote>
<p>That’s an understatement. It’s not clear how “naive” differs from best practice.</p>
<p>Clearly there is value in transforming multiple <code>primary key =</code> queries into a single <code>primary key in</code> query. As in the <code>starships</code> example however, that can be done more simply in the parent resolver. There is more value in not needing a <code>primary key in</code> query at all. Furthermore adding caching to a dataloader avoids the central issue.</p>
<p>Again reminiscent of ORMs, any data layer can add caching. The point is efficiently resolving a query requires context, which strict adherence to single-purpose resolvers explictly disregards.</p>
</section>
<section id="aggregation" class="level2">
<h2 class="anchored" data-anchor-id="aggregation">Aggregation</h2>
<p>The inefficencies becomes even more glaring when moving beyond associative keys. Nearly any aggregation requires knowing what summaries are requested. Such as if the <code>appearsIn</code> field optionally included counts or times. Using SQL as an example again, the query would resemble one of:</p>
<ul>
<li><code>SELECT distinct field FROM ...</code></li>
<li><code>SELECT field, count(*) FROM ... GROUP BY field</code></li>
</ul>
<p>The conditional logic <code>if "count" in requested_fields</code> must exist in some form in the code, because the alternatives are over-fetching or under-fetching. Both of which are far more inefficient in this scenario than in the “select N+1” problem. A dataloader-esque approach is not going to be applicable to “group by” operations.</p>
</section>
<section id="computation" class="level2">
<h2 class="anchored" data-anchor-id="computation">Computation</h2>
<p>One last generalized example: computed fields. What are typically query flags in REST (and <a href="https://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a>) APIs, become field selections in GraphQL.</p>
<p>For example, computing scores in a search engine interface. Instead of a <code>scores: Boolean! = false</code> input option, the more obvious approach would be to skip score calculation when the <code>score</code> field isn’t requested.</p>
<p>As with aggregation, the same pattern recurs. It’s unacceptable to over-fetch, i.e., compute the scores when not needed. It’s worse still to under-fetch, i.e., run some sort of lean search that will find matches and then go back and compute scores later.</p>
</section>
<section id="solution" class="level2">
<h2 class="anchored" data-anchor-id="solution">Solution</h2>
<p>The inescapable conclusion is that in some cases parent resolvers need to know which of their children are being requested. There’s no need to throw away GraphQL’s server-side resolver hierarchy. No one is advocating a thousand line root resolver named <code>RunIt</code> that processes the entire query.</p>
<p>All that’s needed is a conceptual shift which encourages introspecting the <code>GraphQLResolveInfo</code> object. The requested fields are right there waiting to be useful, but good luck finding documentation and examples to that effect. In every non-trivial GraphQL project, this author has used a utility like:</p>
<div id="cell-7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> selections(node):</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return tree of field name selections."""</span></span>
<span id="cb3-3">    nodes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">getattr</span>(node.selection_set, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'selections'</span>, [])</span>
<span id="cb3-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {node.name.value: selections(node) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> node <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> nodes}</span></code></pre></div></div>
</div>
<p>Those fields would be checked or passed to a data layer as needed. For example, in <a href="https://www.djangoproject.com">Django’s</a> ORM, it could be as simple as appending a query set with <code>.values(*selections(*info.nodes))</code>.</p>
<p>Well, almost. The next issue is that typical GraphQL model validators raise an error if required fields are missing. Thanks validator; the field is missing because the client didn’t request it.</p>
<p>This is actually a different age-old problem: equivocating “optional” and “nullable”. GraphQL requires populating all requested fields, and specifiying whether they may be null. Server-side implementations understandably, but still incorrectly, interpret that by making nullables optional and non-nullables required at the model layer. So typically it’s necessary to pad resolved objects with empty (but not null) data.</p>
<p>Although a minor problem, it reveals the bias related to single-purpose resolvers. The point of GraphQL is to efficiently return only the requested fields, yet standard practice in GraphQL models is to require populating fields that haven’t been requested.</p>
<p>Over- and under- fetching can be addressed directly in resolvers, with the data layer’s own interface, instead of hidden behind another abstraction layer.</p>


</section>
</section>

 ]]></description>
  <category>graphql</category>
  <guid>https://coady.github.io/posts/graphql-orm.html</guid>
  <pubDate>Mon, 06 Jul 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Closing files</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/closing-files.html</link>
  <description><![CDATA[ 






<section id="contrarian-view-on-closing-files." class="level1">
<h1>Contrarian view on closing files.</h1>
<p>It has become conventional wisdom to always explicitly close file-like objects, via context managers. The <a href="https://google.github.io/styleguide/pyguide.html#311-files-and-sockets">google style guide</a> is representative:</p>
<blockquote class="blockquote">
<p>Explicitly close files and sockets when done with them. Leaving files, sockets or other file-like objects open unnecessarily has many downsides, including:</p>
</blockquote>
<blockquote class="blockquote">
<p>They may consume limited system resources, such as file descriptors. * Code that deals with many such objects may exhaust those resources unnecessarily if they’re not returned to the system promptly after use. * Holding files open may prevent other actions being performed on them, such as moves or deletion. * Files and sockets that are shared throughout a program may inadvertantly be read from or written to after logically being closed. If they are actually closed, attempts to read or write from them will throw exceptions, making the problem known sooner.</p>
</blockquote>
<blockquote class="blockquote">
<p>Furthermore, while files and sockets are automatically closed when the file object is destructed, tying the life-time of the file object to the state of the file is poor practice, for several reasons: * There are no guarantees as to when the runtime will actually run the file’s destructor. Different Python implementations use different memory management techniques, such as delayed Garbage Collection, which may increase the object’s lifetime arbitrarily and indefinitely. * Unexpected references to the file may keep it around longer than intended (e.g.&nbsp;in tracebacks of exceptions, inside globals, etc).</p>
</blockquote>
<blockquote class="blockquote">
<p>The preferred way to manage files is using the “with” statement:</p>
</blockquote>
<pre><code>with open("hello.txt") as hello_file:
    for line in hello_file:
        print line</code></pre>
<section id="in-theory" class="level2">
<h2 class="anchored" data-anchor-id="in-theory">In theory</h2>
<p>Good points, and why limit this advice to file descriptors? Any resource may be limited or require exclusivity; that’s why they’re called resources. Similarly one should always explicitly call <code>dict.clear</code> when finished with a <code>dict</code>. After all, “there are no guarantees as to when the runtime will actually run the &lt;object’s&gt; destructor. And”code that deals with many such objects may exhaust those resources unnecessarily”, such as memory, or whatever else is in the <code>dict</code>.</p>
<p>But in all seriousness, this advice is applying a notably higher standard of premature optimization to file descriptors than to any other kind of resource. There are plenty of Python projects that are guaranteed to run on CPython for a variety of reasons, where destructors are immediately called. And there are plenty of Python projects where file descriptor usage is just a non-issue. It’s now depressingly commonplace to see this in <code>setup.py</code> files:</p>
<div id="cell-2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"README.md"</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> readme:</span>
<span id="cb2-2">    long_description <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> readme.read()</span></code></pre></div></div>
</div>
<p>Let’s consider a practical example: a <code>load</code> function which is supposed to read and parse data given a file path.</p>
<div id="cell-4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> csv</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load(filepath):</span>
<span id="cb3-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""the supposedly bad way"""</span></span>
<span id="cb3-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> json.load(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(filepath))</span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load(filepath):</span>
<span id="cb3-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""the supposedly good way"""</span></span>
<span id="cb3-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(filepath) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>:</span>
<span id="cb3-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> json.load(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>)</span>
<span id="cb3-12"></span>
<span id="cb3-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load(filepath):</span>
<span id="cb3-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""with a different file format"""</span></span>
<span id="cb3-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(filepath) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>:</span>
<span id="cb3-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> csv.reader(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>)</span></code></pre></div></div>
</div>
<p>Which versions work correctly? Are you sure? If it’s not immediately obvious why one of these is broken, that’s the point. In fact, it’s worth trying out before reading on.</p>
<p>…</p>
<p>The <code>csv</code> version returns an iterator over a closed file. It’s a violation of procedural abstraction to know whether the result of <code>load</code> is lazily evaluated or not; it’s just supposed to implement an interface. Moreover, according to this best practice, it’s <em>impossible</em> to write the <code>csv</code> version correctly. As absurd as it sounds, it’s just an abstraction that can’t exist.</p>
<p>Defiantly clever readers are probably already trying to fix it. Maybe like this:</p>
<div id="cell-6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load(filepath):</span>
<span id="cb4-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(filepath) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>:</span>
<span id="cb4-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> csv.reader(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>)</span></code></pre></div></div>
</div>
<p>No, it will not be fixed. This version only appears to work by <em>not</em> closing the file until the generator is exhausted or collected.</p>
<p>This trivial example has deeper implications. If one accepts this practice, then one must also accept that storing a file handle anywhere, such as on an instance, is also disallowed. Unless of course that object then virally implements it owns context manager, ad infinitum.</p>
<p>Furthermore it demonstrates that often the context is not being managed locally. If a file object is passed another function, then it’s being used outside of the context. Let’s revisit the <code>json</code> version, which works because the file is fully read. Doesn’t a json parser have some expensive parsing to do after it’s read the file? It might even throw an error. And isn’t it desirable, trivial, <a href="https://github.com/python/cpython/blob/master/Lib/json/__init__.py#L274">and likely</a> that the implementation releases interest in the file as soon as possible?</p>
<p>So in reality there are scenarios where the supposedly good way could keep the file open <em>longer</em> than the supposedly bad way. The original inline version does exactly what it’s supposed to do: close the file when all interested parties are done with it. Python uses garbage collection to manage shared resources. Any attempt to pretend otherwise will result in code that is broken, inefficient, or reinventing reference counting.</p>
<p>A true believer now has to accept that <code>json.load</code> is a useless and dangerous wrapper, and that the only correct implementation is:</p>
<div id="cell-8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load(filepath):</span>
<span id="cb5-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(filepath) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>:</span>
<span id="cb5-3">        contents <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>.read()</span>
<span id="cb5-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> json.loads(contents)</span></code></pre></div></div>
</div>
<p>This line of reasoning reduces to the absurd: a file should never be passed or stored anywhere. Next an example where the practice has caused real-world damage.</p>
</section>
<section id="in-practice" class="level2">
<h2 class="anchored" data-anchor-id="in-practice">In practice</h2>
<p><a href="https://requests.readthedocs.io/en/master/">Requests</a> is one of the most popular python packages, and <a href="https://docs.python.org/3/library/http.client.html#module-http.client">officially recommended</a>. It includes a <a href="http://requests.readthedocs.org/en/latest/user/advanced/#session-objects">Session</a> object which supports closing via a context manager. The vast majority of real-world code uses the the top-level functions or single-use sessions.</p>
<div id="cell-10" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.get(...)</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> requests.Session() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> session:</span>
<span id="cb6-4">    response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(...)</span></code></pre></div></div>
</div>
<p>Sessions manage the connection pool, so this pattern of usage is establishing a new connection every time. There are popular standard API clients which seriously do this, for every single request to the same endpoint.</p>
<p>Requests’ documentation prominently states that “Keep-alive and HTTP connection pooling are 100% automatic”. So part of the blame may lay with that phrasing, since it’s only “automatic” if sessions are reused. But surely a large part of the blame is the dogma of closing sockets, and therefore sessions, explicitly. The whole point of a connection pool is that it may leave connections open, so users who genuinely need this granularity are working at the wrong abstraction layer. <code>http.client</code> is already builtin for that level of control.</p>
<p>Tellingly, requests’ own top-level functions didn’t always close sessions. There’s a long history to that code, including a <a href="https://github.com/kennethreitz/requests/commit/3155bc99362a8c6ab136b6a3bb999732617cd2e5">version that only closed sessions on success</a>. An older version was <a href="https://github.com/kennethreitz/requests/issues/1882">causing warnings</a>, when run to check for such warnings, and was being blamed for the <em>appearance</em> of <a href="https://github.com/kennethreitz/requests/issues/1685">leaking memory</a>. Those threads are essentially debating whether a resource pool is “leaking” resources.</p>
</section>
<section id="truce" class="level2">
<h2 class="anchored" data-anchor-id="truce">Truce</h2>
<p>Prior to <code>with</code> being introduced in Python 2.5, it was <em>not</em> recommended that inlined reading of a file required a <code>try... finally</code> block. Far from it, in the past idioms like <code>open(...).read()</code> and <code>for line in open(...)</code> were lauded for being succinct and expressive. But if all this orphaned file descriptor paranoia was well-founded, it would have been a problem back then too.</p>
<p>Finally, let’s address readability. It could be argued (though it rarely is) that showing the reader when the file is closed has inherent value. Conveniently, that tends to align with having opened the file for writing anyway, thereby needing an reference to it. In which case, the readability is approximately equal, and potential pitfalls are more realistic. But readability is genuinely lost when the file would have been opened in a inline expression.</p>
<p>The best practice is unjustifiably special-casing file descriptors, and not seeing its own reasoning through to its logical conclusion. This author proposes advocating for <em>anonymous read-only</em> <code>open</code> expressions. Your setup script is not going to run out of file descriptors because you wrote <code>open("README.md").read()</code>.</p>


</section>
</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/closing-files.html</guid>
  <pubDate>Sun, 05 Jul 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Mutable defaults</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/mutable-defaults.html</link>
  <description><![CDATA[ 






<section id="contrarian-view-on-mutable-default-arguments." class="level1">
<h1>Contrarian view on mutable default arguments.</h1>
<p>The use of <a href="https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments">mutable defaults</a> is probably the most infamous Python gotcha. Default values are evaluated at definition time, which means mutating them will be persistent across multiple calls. Many articles on this topic even use the same <code>append</code> example.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> append_to(element, to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]):</span>
<span id="cb1-2">    to.append(element)</span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> to</span>
<span id="cb1-4"></span>
<span id="cb1-5">append_to(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>[0]</code></pre>
</div>
</div>
<div id="cell-3" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">append_to(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[0, 1]</code></pre>
</div>
</div>
<p>And the solution is invariably to use <code>None</code> instead, and convert as needed.</p>
<div id="cell-5" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> append_to(element, to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb5-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> to <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb5-3">        to <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb5-4">    to.append(element)</span>
<span id="cb5-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> to</span></code></pre></div></div>
</div>
<p>There is another solution to the problem of mutating a default value: don’t do that. More specifically, the problem isn’t using mutables as defaults; the problem is actually mutating them.</p>
<p>If the input from the caller is being mutated, then the caller doesn’t need it returned because the caller already has a reference. This distinction is explicitly encouraged in Python, e.g., <code>list.sort</code> vs.&nbsp;<code>sorted</code>. But it follows that if the input doesn’t need to be returned, then there’s no point in the input being optional. How would the caller know the difference?</p>
<p>The reason why examples like the fluent <code>append</code> seem so contrived is because they are. No one actually wants a function named <code>append</code> to take one argument. The realistic fix would be:</p>
<div id="cell-7" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> append_to(element, to):</span>
<span id="cb6-2">    to.append(element)</span>
<span id="cb6-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> to</span></code></pre></div></div>
</div>
<p>Sure, there are rare occassions where a parameter is mutable but optional, such as a recursive algorithm that’s implicitly passing around its own cache. But this author would wager that given any real-world code that’s been bitten by this gotcha there is:</p>
<ul>
<li>a ~90% chance the function would have a related bug if defaults were evaluated at runtime</li>
<li>a ~95% chance the function has a poor interface</li>
</ul>
<p>What harm does this advice do? Well, it’s caused an over-reaction resulting in using <code>None</code> as the only default, even for immutables. It’s so prevalent that it appears many beginners believe using <code>None</code> is the one and only way of making an argument optional.</p>
<p>Besides immutable types, there are also cases where mutation is irrelevant. Consider the following example adapted from a popular project.</p>
<div id="cell-9" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> List</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, alist: List <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb7-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.alist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> alist <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(alist)</span></code></pre></div></div>
</div>
<p>Notice that the correctness of this code relies on the member list being newly created in either case. What could possibly go wrong with:</p>
<div id="cell-11" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, alist: List <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []):</span>
<span id="cb8-2">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.alist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(alist)</span></code></pre></div></div>
</div>
<p>Or better yet, why not support the more liberal interface.</p>
<div id="cell-13" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Iterable</span>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, alist: Iterable <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ()):</span>
<span id="cb9-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.alist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(alist)</span></code></pre></div></div>
</div>
<p>The point is that there are at least 4 solutions to this problem:</p>
<ol type="1">
<li>use mutable defaults, but don’t mutate them</li>
<li>use immutable substitute defaults with a compatible interface</li>
<li>use <code>None</code> for mutables, and matching types for immutables</li>
<li>use <code>None</code> for all defaults</li>
</ol>
<p>Only #1 is even remotely controversial, yet somehow the status quo has landed on #4. Besides being needlessly verbose, it has another pitfall. Python doesn’t natively support detecting where the argument was actually passed; a sentinel default is required for that. The implementation detail is leaking through the interface, indicating to the caller that <code>None</code> is an acceptable argument to pass <em>explicitly</em>. As if the type hint was <code>Optional[List]</code>, even though that’s not the intention. Factor in using <code>**kwargs</code> - which clearly doesn’t want data padded with nulls - and actual code breakage can result.</p>
<p>Presumably the disdain for option #1 is because it might <em>encourage</em> the gotcha. But it’s disingenous to just let that go unsaid. The implementer is responsible for writing correct code, and the caller sees the right interface. The speculation is that beginners will read code which uses mutable defaults but doesn’t mutate them, and follow the former pattern but not the latter.</p>
<p>As a community, let’s at least push towards option #3. Using empty strings and zeros as defaults is all upside.</p>


</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/mutable-defaults.html</guid>
  <pubDate>Sun, 28 Jun 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Water pouring</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/water-pouring.html</link>
  <description><![CDATA[ 






<section id="how-to-solve-the-water-pouring-puzzle-programmatically." class="level1">
<h1>How to solve the <a href="https://en.wikipedia.org/wiki/Water_pouring_puzzle#Variant_with_taps_and_sinks">water pouring puzzle</a> programmatically.</h1>
<p>Given two jugs of capcity of 3 and 5 liters, acquire exactly 4 liters in a jug. Assume an unlimited water supply, and that jugs can only be filled or emptied, i.e., no estimations.</p>
<p>First to model the data: a mapping of jug sizes to their current quantity. There are 3 primitive operations:</p>
<ul>
<li>filling a jug to capacity</li>
<li>emptying a jug entirely</li>
<li>pouring from a source jug to a destination jug, until either the source is emptied or the destination is full</li>
</ul>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Jugs(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>):</span>
<span id="cb1-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fill(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, size):</span>
<span id="cb1-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[size] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> size</span>
<span id="cb1-4"></span>
<span id="cb1-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> empty(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, size):</span>
<span id="cb1-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[size] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb1-7">    </span>
<span id="cb1-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> pour(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, src, dest):</span>
<span id="cb1-9">        total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[src] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[dest]</span>
<span id="cb1-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[src] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> dest, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb1-11">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>[dest] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(total, dest)</span></code></pre></div></div>
</div>
<p>That’s sufficient to solve the puzzle through sheer brute force: scanning every possible combination breadth-first. Note the below implementations don’t terminate unless a solution is found.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> partial</span>
<span id="cb2-3"></span>
<span id="cb2-4">sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb2-5">operations <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.chain(</span>
<span id="cb2-6">    (partial(Jugs.fill, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>size) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> size <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sizes),</span>
<span id="cb2-7">    (partial(Jugs.empty, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>size) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> size <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sizes),</span>
<span id="cb2-8">    (partial(Jugs.pour, src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>src, dest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dest)</span>
<span id="cb2-9">         <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> src, dest <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.permutations(sizes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)),</span>
<span id="cb2-10">))</span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> search(target):</span>
<span id="cb2-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb2-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> ops <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.product(operations, repeat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n):</span>
<span id="cb2-15">            jugs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Jugs.fromkeys(sizes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb2-16">            states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [op(jugs) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(jugs.values()) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> op <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ops]</span>
<span id="cb2-17">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">any</span>(target <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> state <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> states):</span>
<span id="cb2-18">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> states</span>
<span id="cb2-19"></span>
<span id="cb2-20"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 138 ms, sys: 2.28 ms, total: 140 ms
Wall time: 144 ms</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[(0, 5), (3, 2), (0, 2), (2, 0), (2, 5), (3, 4)]</code></pre>
</div>
</div>
<p>Now to relentlessly simplify the code. The first observation is that an empty source is useless, as is a full destination. So the <code>fill</code> and <code>empty</code> primitives are actually unneeded, and can be integrated into the <code>pour</code> method.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> pour(jugs, src, dest):</span>
<span id="cb5-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> jugs[src]:</span>
<span id="cb5-3">        jugs[src] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> src</span>
<span id="cb5-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> jugs[dest] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> dest:</span>
<span id="cb5-5">        jugs[dest] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb5-6">    total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> jugs[src] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> jugs[dest]</span>
<span id="cb5-7">    jugs[src] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> dest, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb5-8">    jugs[dest] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(total, dest)</span>
<span id="cb5-9"></span>
<span id="cb5-10">operations <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [partial(pour, src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>src, dest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dest) </span>
<span id="cb5-11">               <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> src, dest <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.permutations(sizes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)]</span>
<span id="cb5-12"></span>
<span id="cb5-13"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>CPU times: user 87 µs, sys: 0 ns, total: 87 µs
Wall time: 88.7 µs</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>[(3, 2), (2, 0), (3, 4)]</code></pre>
</div>
</div>
<p>That reduced the search space considerably, but moreover has revealed another simplification: it’s pointless to “undo” a pour. Whether the source was emptied or the destination was filled, whatever reversing the previous pour direction would accomplish could have been done in the first place.</p>
<p>If there were more than 2 jugs, then there could be complex workflows. But with only 2, the first choice in pour directions determines the rest. There are only 2 <em>potential</em> solutions to the puzzle.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> search(target, src, dest):</span>
<span id="cb8-2">    jugs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>.fromkeys((src, dest), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb8-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb8-4">        pour(jugs, src, dest)</span>
<span id="cb8-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(jugs.values())</span>
<span id="cb8-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> target <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> jugs.values():</span>
<span id="cb8-7">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb8-8"></span>
<span id="cb8-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>[(2, 3), (0, 2), (4, 3)]</code></pre>
</div>
</div>
<div id="cell-9" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>[(0, 3), (1, 5), (0, 1), (0, 4)]</code></pre>
</div>
</div>
<p>And both of them are valid solutions. The solution to the puzzle is quite simply: keep pouring. It doesn’t even matter which to start with.</p>
<p>But it can be further simplified. Now it’s clear that the <code>jug</code> data structure is only providing modular arithmetic.</p>
<div id="cell-11" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> search(target, src, dest):</span>
<span id="cb12-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.count(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb12-3">        quot, rem <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">divmod</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> src <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> target, dest)</span>
<span id="cb12-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> rem:</span>
<span id="cb12-5">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>quot</span>
<span id="cb12-6"></span>
<span id="cb12-7">search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>(2, -2)</code></pre>
</div>
</div>
<div id="cell-12" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">search(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>(3, -1)</code></pre>
</div>
</div>
<div id="cell-13" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;jupyter&quot;,&quot;value&quot;:{&quot;outputs_hidden&quot;:true}}" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span></code></pre></div></div>
</div>
<p>The puzzle is looking for integer solutions to <img src="https://latex.codecogs.com/png.latex?%0A%5C%203x%20+%205y%20=%204%0A"> Which is known as a linear <a href="https://en.wikipedia.org/wiki/Diophantine_equation">Diophantine equation</a>, and must have a solution because <img src="https://latex.codecogs.com/png.latex?4"> is a multiple of <img src="https://latex.codecogs.com/png.latex?gcd(3,%205)">.</p>


</section>

 ]]></description>
  <category>puzzles</category>
  <guid>https://coady.github.io/posts/water-pouring.html</guid>
  <pubDate>Sun, 14 Jun 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Coin balance</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/coin-balance.html</link>
  <description><![CDATA[ 






<section id="how-to-solve-the-coin-balance-puzzle-programmatically." class="level1">
<h1>How to solve the coin <a href="https://en.wikipedia.org/wiki/Balance_puzzle#Twelve-coin_problem">balance puzzle</a> programmatically.</h1>
<p>Given a balance and a set of coins, which are all equal in weight except for one, determine which coin is of different weight in as few weighings as possible.</p>
<blockquote class="blockquote">
<p>Twelve-coin problem</p>
</blockquote>
<blockquote class="blockquote">
<p>A more complex version has twelve coins, eleven or twelve of which are identical. If one is different, we don’t know whether it is heavier or lighter than the others. This time the balance may be used three times to determine if there is a unique coin—and if there is, to isolate it and determine its weight relative to the others. (This puzzle and its solution first appeared in an article in 1945.[2]) The problem has a simpler variant with three coins in two weighings, and a more complex variant with 39 coins in four weighings.</p>
</blockquote>
<p>First to model the data:</p>
<ul>
<li>An <code>enum</code> to represent different weights. Following the ternary comparison convention, such as Python 2’s <a href="https://docs.python.org/2.7/library/functions.html?highlight=cmp#cmp">cmp</a>, is convenient.</li>
<li>An object to represent the balance. For testing, it will need to be configurable with the target coin and relative weight.</li>
<li>An object to represent a coin and its state. A <code>class</code> is tempting, but the most useful data structure would keep the coins grouped by their known (or unknown) state anyway. So any hashable unique identifier is sufficient.</li>
</ul>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> enum</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Weight(enum.IntEnum):</span>
<span id="cb1-4">    LIGHT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb1-5">    EVEN <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb1-6">    HEAVY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Balance:</span>
<span id="cb1-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, coin, weight: Weight):</span>
<span id="cb1-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> coin</span>
<span id="cb1-11">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> weight</span>
<span id="cb1-12"></span>
<span id="cb1-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> weigh(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, left: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, right: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>):</span>
<span id="cb1-14">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return relative Weight of left side to right side."""</span></span>
<span id="cb1-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(left) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(right)</span>
<span id="cb1-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> left:</span>
<span id="cb1-17">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight</span>
<span id="cb1-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> right:</span>
<span id="cb1-19">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Weight(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight)</span>
<span id="cb1-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Weight.EVEN</span>
<span id="cb1-21"></span>
<span id="cb1-22">coins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcdefghijkl'</span></span>
<span id="cb1-23"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(coins) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span></span>
<span id="cb1-24">balance <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Balance(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>, Weight.LIGHT)</span>
<span id="cb1-25"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> balance.weigh(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'b'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> Weight.LIGHT</span>
<span id="cb1-26"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> balance.weigh(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'b'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'c'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> Weight.EVEN</span>
<span id="cb1-27"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> balance.weigh(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'b'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> Weight.HEAVY</span></code></pre></div></div>
</div>
<p>As is typical with <a href="https://en.wikipedia.org/wiki/Induction_puzzles">induction puzzles</a>, the constants chosen are just large enough to thwart an iterative approach. The 2 weighing variation would be trivial enough for most people to brute force the solution. Whereas 4 weighings would already be such a large decision tree, it would be tedious to even output. The easier approach is solve the puzzle recursively and more generally, for any number of coins and weighings.</p>
<p>So what can be done in a single weighing? Clearly all weighings must have an equal number of coins on each side, else nothing is learned. If it balances, then the different coin is in the unweighed group. If it doesn’t balance, then the different coin is in the weighed group, but additionally it is known whether each coin would be heavy or light based on which side it was on. This is the crucial insight: there’s a variant recursive puzzle embedded inside this puzzle.</p>
<p>The <a href="https://en.wikipedia.org/wiki/Tower_of_Hanoi">Towers of Hanoi</a> is a classic puzzle often used in computer science curricula to teach recursion. This one would suitable as a subsequent more advanced problem.</p>
<p>So what can be done with known coins in a single weighing? If it balances, then as before the different coin is in the unweighed group. But if it doesn’t balance, then which way can be used to further narrow the coins. Consider the heavier side; the different coin must be one of the heavy ones on that side, or one of the light ones on the other side. Therefore the coins can be split into 2 equal sized groups by putting equal numbers of heavy coins on each side, and equal numbers of light coins on each side. One obstacle is that if there aren’t an even number, there will need to be filler coins just to balance. But that won’t be a problem after the first weighing.</p>
<p>Now we can implement a solution to the sub-problem, and build the need for filler coins into the balance implementation. A generator is used so that the output of each weighing can be displayed.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Balance:</span>
<span id="cb2-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, coin, weight: Weight):</span>
<span id="cb2-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> coin</span>
<span id="cb2-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> weight</span>
<span id="cb2-7">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>()</span>
<span id="cb2-8"></span>
<span id="cb2-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> weigh(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, left: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, right: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>):</span>
<span id="cb2-10">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return relative Weight of left side to right side."""</span></span>
<span id="cb2-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(left) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(right)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler)</span>
<span id="cb2-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> left:</span>
<span id="cb2-13">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight</span>
<span id="cb2-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.coin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> right:</span>
<span id="cb2-15">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Weight(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weight)</span>
<span id="cb2-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Weight.EVEN</span>
<span id="cb2-17"></span>
<span id="cb2-18">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> find(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, light: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>, heavy: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>):</span>
<span id="cb2-19">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Recursively find target coin from sets of potentially light and heavy coins."""</span></span>
<span id="cb2-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> light, heavy</span>
<span id="cb2-21">        union <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> heavy</span>
<span id="cb2-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(union) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb2-23">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb2-24">        left, right <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>()</span>
<span id="cb2-25">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># split into 3 groups</span></span>
<span id="cb2-26">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> start, third <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>([left, right]):</span>
<span id="cb2-27">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (light, heavy):</span>
<span id="cb2-28">                third.update(itertools.islice(group, start, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb2-29">        weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weigh(left, right)</span>
<span id="cb2-30">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb2-31">            light, heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> left), (heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> right)</span>
<span id="cb2-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb2-33">            light, heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> right), (heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> left)</span>
<span id="cb2-34">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb2-35">            light, heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> left <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> right), (heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> left <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> right)</span>
<span id="cb2-36">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler.update(union <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> heavy)</span>
<span id="cb2-37">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.find(light, heavy)</span>
<span id="cb2-38"></span>
<span id="cb2-39">balance <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Balance(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>, Weight.LIGHT)</span>
<span id="cb2-40"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> light, heavy <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> balance.find(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abc'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'def'</span>)):</span>
<span id="cb2-41">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(light), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(heavy))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>cba dfe
a e
a </code></pre>
</div>
</div>
<p>Now with the sub-problem solved, there’s just one thing missing for the main puzzle. In the known case, splitting into 3 equal sized groups is cleary optimal. But in the unknown case, we need to know how many coins to exclude from the weighing. This requires computing how many coins can be handled in the subsolution. Luckily it’s a trivial <a href="https://en.wikipedia.org/wiki/Recurrence_relation">recurrence relation</a>: <code>n</code> weighings can solve 3 times the number of <code>n - 1</code> weighings. <img src="https://latex.codecogs.com/png.latex?%0A%5Cprod_%7B%7D%5En%203%20=%203%5En%0A"></p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Balance(Balance):</span>
<span id="cb4-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> solve(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, coins):</span>
<span id="cb4-3">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Recursively find target coin."""</span></span>
<span id="cb4-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb4-5">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb4-6">        weigh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(itertools.islice(coins, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> (count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler)))</span>
<span id="cb4-7">        exclude <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(coins) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> weigh</span>
<span id="cb4-8">        left, right <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(itertools.islice(weigh, start, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> start <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb4-9">        weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weigh(left, right)</span>
<span id="cb4-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler.update(exclude <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> weight <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> weigh)</span>
<span id="cb4-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb4-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.find(left, right)</span>
<span id="cb4-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb4-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.find(right, left)</span>
<span id="cb4-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb4-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.solve(count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, exclude)</span>
<span id="cb4-17"></span>
<span id="cb4-18">balance <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Balance(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>, Weight.LIGHT)</span>
<span id="cb4-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> light, heavy <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> balance.solve(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, coins):</span>
<span id="cb4-20">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(light), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(heavy))</span>
<span id="cb4-21"></span>
<span id="cb4-22"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> coin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> coins:</span>
<span id="cb4-23">    light, heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(Balance(coin, Weight.LIGHT).solve(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, coins))[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> light <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> {coin} <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> heavy</span>
<span id="cb4-25">    light, heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(Balance(coin, Weight.HEAVY).solve(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, coins))[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> light <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> heavy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> {coin}</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>dbah fceg
a e
a </code></pre>
</div>
</div>
<p>The puzzle is solved. There’s one last simplifcation that can be made, but requires a bit more math background. Ideally we wouldn’t need to know the objective number of weighings; the algorithm would just solve any set of coins as efficiently as possible. To do that, the number of coins that can be solved has to be computed. As was done above, but this recurrence relation is more advanced: each weighing can solve <code>3 ^ n</code> more coins. <img src="https://latex.codecogs.com/png.latex?%0A%5Csum_%7Bk=0%7D%5E%7Bn-1%7D%203%5Ek%20=%20(3%5En%20-%201)%20/%202%0A"></p>
<p>With that calculation inverted, the <code>count</code> can be removed from the interface</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Balance(Balance):</span>
<span id="cb6-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> solve(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, coins):</span>
<span id="cb6-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> coins:</span>
<span id="cb6-6">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb6-7">        count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> math.ceil(math.log(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(coins) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb6-8">        weigh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(itertools.islice(coins, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> (count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler)))</span>
<span id="cb6-9">        exclude <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(coins) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> weigh</span>
<span id="cb6-10">        left, right <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(itertools.islice(weigh, start, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> start <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb6-11">        weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.weigh(left, right)</span>
<span id="cb6-12">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.filler.update(exclude <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> weight <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> weigh)</span>
<span id="cb6-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.find(left, right)</span>
<span id="cb6-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.find(right, left)</span>
<span id="cb6-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb6-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.solve(exclude)</span>
<span id="cb6-19"></span>
<span id="cb6-20">balance <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Balance(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>, Weight.LIGHT)</span>
<span id="cb6-21"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> light, heavy <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> balance.solve(coins):</span>
<span id="cb6-22">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(light), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(heavy))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>dbah fceg
a e
a </code></pre>
</div>
</div>
<p>Notice the formula indicates it’s possible to do 13 coins in 3 weighings, and it would be with a filler coin to balance out the 9 that need weighing.</p>


</section>

 ]]></description>
  <category>puzzles</category>
  <guid>https://coady.github.io/posts/coin-balance.html</guid>
  <pubDate>Sun, 07 Jun 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Hat puzzle</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/hat-puzzle.html</link>
  <description><![CDATA[ 






<section id="how-to-solve-the-hat-puzzle-programmatically." class="level1">
<h1>How to solve the <a href="https://en.wikipedia.org/wiki/Hat_puzzle#Ten-Hat_Variant">Hat puzzle</a> programmatically.</h1>
<blockquote class="blockquote">
<p>Ten-Hat Variant</p>
</blockquote>
<blockquote class="blockquote">
<p>In this variant there are 10 prisoners and 10 hats. Each prisoner is assigned a random hat, either red or blue, but the number of each color hat is not known to the prisoners. The prisoners will be lined up single file where each can see the hats in front of him but not behind. Starting with the prisoner in the back of the line and moving forward, they must each, in turn, say only one word which must be “red” or “blue”. If the word matches their hat color they are released, if not, they are killed on the spot. A friendly guard warns them of this test one hour beforehand and tells them that they can formulate a plan where by following the stated rules, 9 of the 10 prisoners will definitely survive, and 1 has a 50/50 chance of survival. What is the plan to achieve the goal?</p>
</blockquote>
<p>This puzzle involves three concepts common to classic logic puzzles:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Theory_of_mind">Theory of mind</a></li>
<li><a href="https://en.wikipedia.org/wiki/Functional_fixedness">Functional fixedness</a></li>
<li><a href="https://en.wikipedia.org/wiki/Induction_puzzles">Induction</a></li>
</ul>
<p>Theory of mind comes into play because each prisoner has differing knowledge, but assumes everyone else will think similarly. Functional fixedness occurs more subtly; each prisoner may state a color only to convey information. But because the information is encoded as a color, it tends to focus thinking on the colors themselves. So to combat that cognitive bias, first create a different enumeration to represent statements. Any binary <code>enum</code> can be mapped back to colors, so why not <code>bool</code>.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">colors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'red'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'blue'</span></span>
<span id="cb1-2">colors[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>], colors[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>('red', 'blue')</code></pre>
</div>
</div>
<p>Which leaves induction: solve the puzzle for the base case (smallest size) first, and then methodically build on that solution. In the case of 1 prisoner, they have no information a priori, and therefore have a 50/50 chance of survival regardless of strategy. This variant of the puzzle already gives the optimal goal, so we know that everyone but the 1st can say their color and be saved, while the 1st can devote their answer to the common cause.</p>
<p>In the case of 2 prisoners, obviously the 1st can say the color of the 2nd. That approach does not scale; it is the path to functional fixedness. Instead, methodically enumerate all possible statements and colors to determine if there is an unambiguous solution.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>], colors))</span>
<span id="cb3-2">table</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[(False, 'red'), (True, 'blue')]</code></pre>
</div>
</div>
<p>The above table is a general solution with no assumptions other than the arbitrary ordering of enums. While it may appear absurdly pedantic, it represents a rule set which is key to building a recursive solution.</p>
<p>In the case of the 3rd prisoner, clearly they can not just repeat the above rule set, because the 3rd would receive no information. But there are only 2 choices, so the only option is to follow the <em>opposite</em> rule set, depending on the 3rd color.</p>
<p>The crucial step is to build off of the existing <code>table</code>.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [row <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> colors[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> table] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> colors[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> table]</span>
<span id="cb5-2">table</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>[(False, 'red', 'red'),
 (True, 'blue', 'red'),
 (True, 'red', 'blue'),
 (False, 'blue', 'blue')]</code></pre>
</div>
</div>
<p>The solution is valid if each prisoner is able to narrow the possibilities to a unique row based on the colors they hear and see.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> collections</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test(table):</span>
<span id="cb7-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Assert that the input table is a valid solution."""</span></span>
<span id="cb7-5">    (size,) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>, table))</span>
<span id="cb7-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(size):</span>
<span id="cb7-7">        counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> collections.Counter(row[:index] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> row[index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> table)</span>
<span id="cb7-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(counts.values()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> {<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>}</span>
<span id="cb7-9"></span>
<span id="cb7-10">test(table)</span></code></pre></div></div>
</div>
<p>The general solution is simply the above logic in recursive form, with a parametrized size.</p>
<div id="cell-10" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> solve(count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>):</span>
<span id="cb8-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate a flat table of all spoken possibilities."""</span></span>
<span id="cb8-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb8-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb8-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb8-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> solve(count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb8-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> row <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> colors[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb8-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> colors[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:]</span>
<span id="cb8-9"></span>
<span id="cb8-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(solve(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>[(False, 'red', 'red'),
 (True, 'red', 'blue'),
 (True, 'blue', 'red'),
 (False, 'blue', 'blue')]</code></pre>
</div>
</div>
<p>The complicated puzzle is actually a trivial recurrence relation: <img src="https://latex.codecogs.com/png.latex?%0A2%5En%20=%202%5E%7Bn-1%7D%20*%202%0A"> There are <img src="https://latex.codecogs.com/png.latex?2%5En"> states of the prisoners, and each prisoner has <img src="https://latex.codecogs.com/png.latex?n-1"> bits of data. So an additional bit of data from the first is sufficient to solve the puzzle.</p>
<div id="cell-12" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(solve(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>))</span>
<span id="cb10-2">test(table)</span>
<span id="cb10-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(table)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>512</code></pre>
</div>
</div>
<div id="cell-13" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">table[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>[(False, 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red'),
 (True, 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'blue'),
 (True, 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'blue', 'red')]</code></pre>
</div>
</div>
<p>The puzzle is solved, but the output is of exponential size, certainly not the succinct solution which makes the puzzle famous. But instead of relying on a flash of insight, this approach produces not just <em>a</em> solution, but <em>the</em> solution. The only arbitrary decision made was the enumeration. Therefore it must be the case that the solution can be summarized.</p>
<p>First, it would be helpful to group the solution by the 1st statement. Any summary function would have to ensure that there is no collision in the grouped possibilities.</p>
<div id="cell-15" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> collections.defaultdict(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>)</span>
<span id="cb14-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> table:</span>
<span id="cb14-3">    groups[row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]].add(row[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:])</span>
<span id="cb14-4">groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> groups[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>], groups[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>]</span>
<span id="cb14-5"></span>
<span id="cb14-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> summarize(func, groups):</span>
<span id="cb14-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Apply summary function to groups and assert uniqueness."""</span></span>
<span id="cb14-8">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(func, group)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups)</span>
<span id="cb14-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>.isdisjoint(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>groups)</span>
<span id="cb14-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> groups</span>
<span id="cb14-11"></span>
<span id="cb14-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> summarize(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> g: g, groups) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> groups</span>
<span id="cb14-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>, groups))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>(256, 256)</code></pre>
</div>
</div>
<p>Now what summaries to attempt? Well there are few properties of sequences to work with: size and order. They are all the same size, so that won’t help. That leaves ordering, which can be easily tested by sorting.</p>
<div id="cell-17" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">summarize(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> g: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(g)), groups)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>({('blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'red'),
  ('blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'red', 'red', 'red'),
  ('blue', 'blue', 'blue', 'blue', 'red', 'red', 'red', 'red', 'red'),
  ('blue', 'blue', 'red', 'red', 'red', 'red', 'red', 'red', 'red'),
  ('red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red')},
 {('blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue'),
  ('blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'red', 'red'),
  ('blue', 'blue', 'blue', 'blue', 'blue', 'red', 'red', 'red', 'red'),
  ('blue', 'blue', 'blue', 'red', 'red', 'red', 'red', 'red', 'red'),
  ('blue', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red')})</code></pre>
</div>
</div>
<p>Success. Now that order does not matter, the appropriate data structure is a multiset (a.k.a. bag). Each prisoner can keep track of only how many of each color they hear and see.</p>
<div id="cell-19" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">summarize(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> g: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">frozenset</span>(collections.Counter(g).items()), groups)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>({frozenset({('blue', 8), ('red', 1)}),
  frozenset({('blue', 2), ('red', 7)}),
  frozenset({('blue', 6), ('red', 3)}),
  frozenset({('blue', 4), ('red', 5)}),
  frozenset({('red', 9)})},
 {frozenset({('blue', 1), ('red', 8)}),
  frozenset({('blue', 7), ('red', 2)}),
  frozenset({('blue', 5), ('red', 4)}),
  frozenset({('blue', 3), ('red', 6)}),
  frozenset({('blue', 9)})})</code></pre>
</div>
</div>
<p>Since there are only 2 colors which sum to a constant, keeping track of just one is sufficient.</p>
<div id="cell-21" class="cell" data-execution_count="11">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">summarize(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> g: g.count(colors[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]), groups)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="11">
<pre><code>({1, 3, 5, 7, 9}, {0, 2, 4, 6, 8})</code></pre>
</div>
</div>
<p>There’s one last pattern to the numbers, which can be used to achieve <a href="https://en.wiktionary.org/wiki/parity">parity</a> with the canonical solution.</p>


</section>

 ]]></description>
  <category>puzzles</category>
  <guid>https://coady.github.io/posts/hat-puzzle.html</guid>
  <pubDate>Sat, 11 Jan 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Split an Iterable</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/split-an-iterable.html</link>
  <description><![CDATA[ 






<section id="split-an-iterable-into-equal-sized-chunks." class="level1">
<h1>Split an iterable into equal sized chunks.</h1>
<p>A common task and interview question, with many variants. It’s frequently <a href="http://stackoverflow.com/questions/312443/">asked and answered</a> in a way that’s suboptimal and only handles <a href="http://stackoverflow.com/questions/6822725/">one specific case</a>. The goal here is to present definitive, general, and efficient solutions.</p>
<p>The first variant is whether or not the chunks will overlap. Although this could be generalized into a <code>step</code> parameter, it’s nearly always the case that <code>step in (1, size)</code>.</p>
<p>The second variant is whether the tail of the data should be returned, if it’s not of equal size. Clearly when <code>step == 1</code> that’s unlikely to be desirable. However, when <code>step == size</code>, that would seem to be the natural choice. And again when <code>1 &lt; step &lt; size</code>, the desired behavior isn’t clear at all.</p>
<p>The third variant is whether to slice sequences, or support any iterable. Obviously working for any iterable would be ideal, but it’s also likely a user would expect slices given a sequence, particularly in the case of strings.</p>
<p>So this author feels it’s best to split the problem in 2 distinct cases: a sliding <code>window</code> for overlapping sequences, and <code>chunks</code> for discrete sequences. In each case, supporting iterables and using advanced iterator algebra for a minimal and efficient solution.</p>
<section id="window" class="level2">
<h2 class="anchored" data-anchor-id="window">Window</h2>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> window(iterable, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb1-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate a sliding window of values."""</span></span>
<span id="cb1-5">    its <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.tee(iterable, size)</span>
<span id="cb1-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(itertools.islice(it, index, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index, it <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(its)))</span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(window(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]</code></pre>
</div>
</div>
<p>That’s simple, and close to optimal. There is slight overhead in iterating an <code>islice</code> object, so a minor variant would be to force the step-wise iteration in advance.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> collections</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> window(iterable, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb3-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate a sliding window of values."""</span></span>
<span id="cb3-5">    its <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itertools.tee(iterable, size)</span>
<span id="cb3-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index, it <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(its):</span>
<span id="cb3-7">        collections.deque(itertools.islice(it, index), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># exhaust iterator</span></span>
<span id="cb3-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>its)</span>
<span id="cb3-9"></span>
<span id="cb3-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(window(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]</code></pre>
</div>
</div>
</section>
<section id="chunks" class="level2">
<h2 class="anchored" data-anchor-id="chunks">Chunks</h2>
<p>A lesser-known and under-utilized feature of <code>iter</code> is that in can take a callable (of no arguments) and a sentinel to create an iterator. A perfect use case of the “loop and a half” idiom.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> chunks(iterable, size):</span>
<span id="cb5-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Generate adjacent chunks of data"""</span></span>
<span id="cb5-3">    it <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(iterable)</span>
<span id="cb5-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(itertools.islice(it, size)), ())</span>
<span id="cb5-5"></span>
<span id="cb5-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(chunks(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>[('a', 'b', 'c'), ('d', 'e')]</code></pre>
</div>
</div>
<p>This should also be optimal, for reasonable sizes.</p>
</section>
<section id="sequences-with-dispatch" class="level2">
<h2 class="anchored" data-anchor-id="sequences-with-dispatch">Sequences with dispatch</h2>
<p>Rather than explicitly check <code>isinstance</code>, this is a perfect use case for <code>functools.singledispatch</code>.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> functools</span>
<span id="cb7-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Sequence</span>
<span id="cb7-3"></span>
<span id="cb7-4">window <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> functools.singledispatch(window)</span>
<span id="cb7-5"></span>
<span id="cb7-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@window.register</span></span>
<span id="cb7-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _(seq: Sequence, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>):</span>
<span id="cb7-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb7-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> seq[index:index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> size]</span>
<span id="cb7-10"></span>
<span id="cb7-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(window(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>['ab', 'bc', 'cd', 'de']</code></pre>
</div>
</div>
<div id="cell-9" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(window(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]</code></pre>
</div>
</div>
<div id="cell-10" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> functools.singledispatch(chunks)</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@chunks.register</span></span>
<span id="cb11-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _(seq: Sequence, size):</span>
<span id="cb11-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq), size):</span>
<span id="cb11-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> seq[index:index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> size]</span>
<span id="cb11-7"></span>
<span id="cb11-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(chunks(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>['abc', 'de']</code></pre>
</div>
</div>
<div id="cell-11" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(chunks(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'abcde'</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>[('a', 'b', 'c'), ('d', 'e')]</code></pre>
</div>
</div>


</section>
</section>

 ]]></description>
  <category>interviews</category>
  <guid>https://coady.github.io/posts/split-an-iterable.html</guid>
  <pubDate>Sat, 28 Dec 2019 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Accumulator</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/accumulator.html</link>
  <description><![CDATA[ 






<section id="a-paul-graham-classic-the-accumulator-function." class="level1">
<h1>A <a href="http://www.paulgraham.com/icad.html">Paul Graham classic</a>, the accumulator function.</h1>
<blockquote class="blockquote">
<p>As an illustration of what I mean about the relative power of programming languages, consider the following problem. We want to write a function that generates accumulators– a function that takes a number n, and returns a function that takes another number i and returns n incremented by i.</p>
</blockquote>
<blockquote class="blockquote">
<p>(That’s incremented by, not plus. An accumulator has to accumulate.)</p>
</blockquote>
<blockquote class="blockquote">
<p>In Common Lisp this would be</p>
</blockquote>
<blockquote class="blockquote">
<p><code>(defun foo (n) (lambda (i) (incf n i)))</code></p>
</blockquote>
<blockquote class="blockquote">
<p>…</p>
</blockquote>
<blockquote class="blockquote">
<p>If you try to translate the Lisp/Perl/Smalltalk/Javascript code into Python you run into some limitations. Because Python doesn’t fully support lexical variables, you have to create a data structure to hold the value of n.&nbsp;And although Python does have a function data type, there is no literal representation for one (unless the body is only a single expression) so you need to create a named function to return. This is what you end up with:</p>
</blockquote>
<blockquote class="blockquote">
<p><code>def foo(n): s = [n] def bar(i): s[0] += i return s[0]  return bar</code></p>
</blockquote>
<blockquote class="blockquote">
<p>Python users might legitimately ask why they can’t just write</p>
</blockquote>
<blockquote class="blockquote">
<p><code>def foo(n): return lambda i: return n += i</code></p>
</blockquote>
<blockquote class="blockquote">
<p>or even</p>
</blockquote>
<blockquote class="blockquote">
<p><code>def foo(n): lambda i: n += i</code></p>
</blockquote>
<blockquote class="blockquote">
<p>and my guess is that they probably will, one day. (But if they don’t want to wait for Python to evolve the rest of the way into Lisp, they could always just…)</p>
</blockquote>
<p>There are <a href="https://en.wikipedia.org/wiki/Function_object#In_Python">other solutions</a>, using function attributes or instances with a <code>__call__</code> method, but none are substantially more elegant. The challenge predates Python 3, which introduced the <code>nonlocal</code> keyword, making this the presumably preferred solution:</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> foo(n):</span>
<span id="cb1-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> inc(x):</span>
<span id="cb1-3">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">nonlocal</span> n</span>
<span id="cb1-4">        n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> x</span>
<span id="cb1-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb1-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> inc</span>
<span id="cb1-7"></span>
<span id="cb1-8">acc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> foo(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb1-9">acc(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-10">acc(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>3</code></pre>
</div>
</div>
<p>There was also yet another alternative as of Python 2.6: using a generator as a coroutine.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> foo(n):</span>
<span id="cb3-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb3-3">        n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb3-4"></span>
<span id="cb3-5">acc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> foo(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(acc)</span>
<span id="cb3-7">acc.send(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb3-8">acc.send(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>3</code></pre>
</div>
</div>
<p>To satisfy the challenge, that would need to be wrapped with a decorator. The triple <code>partial</code> expression below may seem a little obtuse, but it’s not as bad as it looks. Just unwind it one step at a time.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> partial</span>
<span id="cb5-2"></span>
<span id="cb5-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@partial</span>(partial, partial)</span>
<span id="cb5-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> coroutine(func, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb5-5">    gen <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb5-6">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(gen)</span>
<span id="cb5-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> gen.send</span>
<span id="cb5-8"></span>
<span id="cb5-9">coroutine</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>functools.partial(&lt;class 'functools.partial'&gt;, &lt;function coroutine at 0x10bf970e0&gt;)</code></pre>
</div>
</div>
<div id="cell-7" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@coroutine</span></span>
<span id="cb7-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> foo(n):</span>
<span id="cb7-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb7-4">        n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> n</span>
<span id="cb7-5"></span>
<span id="cb7-6">foo</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>functools.partial(&lt;function coroutine at 0x10bf970e0&gt;, &lt;function foo at 0x10bf7eb90&gt;)</code></pre>
</div>
</div>
<div id="cell-8" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">acc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> foo(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb9-2">acc</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>&lt;function generator.send&gt;</code></pre>
</div>
</div>
<div id="cell-9" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">acc(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb11-2">acc(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>3</code></pre>
</div>
</div>
<p>But what’s the most Pythonic solution? This author would argue… don’t. In my experience, I have never really needed <code>global</code> or <code>nonlocal</code> in production code. Typically it’s because the objects in question are <em>mutable</em>, so it’s not necessary to rebind a name in a different scope to a new object.</p>
<p>A typical tell of these kinds of code challenges are that they focus on the interface or implementation exclusively, never both in context. Python numbers are immutable, and have syntactic support for incrementing, so there’s nothing more readable about <code>acc(...)</code> instead of <code>n += ...</code>.</p>
<p>Futhermore, the accumulator object is intended to be used repeatedly, such as in a loop. In a language with such strong iteration support as Python, it’s extremely likely that accumulation will occur in a iterative loop. Indeed, the <em>real</em> accumulator has since been added to the standard library.</p>
<div id="cell-11" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb13-2"></span>
<span id="cb13-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(itertools.accumulate(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]</code></pre>
</div>
</div>


</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/accumulator.html</guid>
  <pubDate>Mon, 28 May 2018 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Map and Filter</title>
  <dc:creator>A. Coady</dc:creator>
  <link>https://coady.github.io/posts/map-and-filter.html</link>
  <description><![CDATA[ 






<section id="contrarian-view-on-map-and-filter." class="level1">
<h1>Contrarian view on <code>map</code> and <code>filter</code>.</h1>
<p>Although <a href="https://www.python.org/dev/peps/pep-0008/">PEP 8</a> is silent on the topic, it’s become recommended in many Python circles to eschew <code>map</code> and <code>filter</code> in favor of generator expressions or list comprehensions. For example, this <a href="http://stackoverflow.com/questions/5426754/google-python-style-guide">Stack Overflow question</a> received and accepted a typical response. Ironically, that question misquoted the <a href="https://google.github.io/styleguide/pyguide.html?showone=Deprecated_Language_Features#Deprecated_Language_Features">google style guide</a>, which this author happens to agree with.</p>
<blockquote class="blockquote">
<p>Use list comprehensions and for loops instead of filter and map <em>when the function argument would have been an inlined lambda anyway</em>. [emphasis added]</p>
</blockquote>
<p>The style guide also shows a non-lambda version as a positive example: &gt; <code>map(math.sqrt, data)</code> # Ok. No inlined lambda expression.</p>
<p>First, a brief history of how the Python community arrived at this state.</p>
<section id="python-1" class="level2">
<h2 class="anchored" data-anchor-id="python-1">Python 1</h2>
<p>Prior to version 2.0, Python had neither list comprehensions nor nested scopes. Therefore simple <code>map</code> and <code>filter</code> operations had to use a <code>for... append</code> loop, or <code>lambda</code>. But the lacked of nested scopes was inherently crippling to the latter approach.</p>
<div id="cell-2" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> y: y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>&lt;map at 0x108e57250&gt;</code></pre>
</div>
</div>
<p>A <code>NameError</code> would have been raised on <code>x</code>, because it’s not defined in the inner scope. One clever work-around was to shadow default arguments.</p>
<div id="cell-4" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb3-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> y, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>x: y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>[0, 2, 4, 6, 8]</code></pre>
</div>
</div>
<p>Unsurprisingly, that was widely viewed as an ugly hack. Many resigned themselves to <code>for... append</code> loops instead.</p>
</section>
<section id="python-2" class="level2">
<h2 class="anchored" data-anchor-id="python-2">Python 2</h2>
<p>Then Python added list comprehensions in 2.0, and that became the <a href="https://en.wikipedia.org/wiki/Zen_of_Python">one obvious way</a> to do it.</p>
<div id="cell-6" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb5-2">[y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> y <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>[0, 2, 4, 6, 8]</code></pre>
</div>
</div>
<p>Python acquired nested scopes in the next version, 2.1, but the damage was done. Functional programming in Python in general, and <code>lambda</code> in particular, was widely frowned upon. Even though the lack of nested scopes affected all inner functions used in any context; it was never really about <code>lambda</code> per se.</p>
</section>
<section id="python-3" class="level2">
<h2 class="anchored" data-anchor-id="python-3">Python 3</h2>
<p>It’s sometimes claimed to this day that <code>map</code> and <code>filter</code> only exist for backwards compatibility. But that belies the history of Python 3. <code>map</code>, <code>filter</code>, and <code>reduce</code> were all considered for removal. But only <code>reduce</code> was banished to the <code>functools</code> module. <code>map</code> and <code>filter</code> were not only retained, but updated to return iterators.</p>
<p>So it’s already dubious to claim that using a built-in is unapproved. But the real point is that <code>map</code> and <code>filter</code> remain a higher level abstraction. Sure, with <code>lambda</code> there are the same number of logical components, and it’s just a matter of syntactic sugar. But there is some abstraction value when the functions already have a name.</p>
<p>It’s also commonly pointed out that generator expressions are superior because they can do a <code>map</code> and <code>filter</code> simultaneously, but crucially only if the <code>filter</code> comes first. Consider this task: normalizing an iterable of strings.</p>
<div id="cell-8" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">values <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sample '</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' '</span></span>
<span id="cb7-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.strip, values)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>['sample']</code></pre>
</div>
</div>
<p>Note <code>list</code> is only being used for printing, and should be ignored for the sake of comparisons.</p>
<p>As for the alternative, surely calling <code>strip</code> twice to use a single expression is just plain cheating. So really the only option is:</p>
<div id="cell-10" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">[value <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (value.strip() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> values) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> value]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>['sample']</code></pre>
</div>
</div>
<p>Some would consider nested comprehensions already enough to separate with a temporary name. But that’s inadvertently acknowledging how much more verbose it is.</p>
<p>Can it really be claimed that the latter is more readable than the former? It’s just boilerplate, which never seems acknowledged in small examples. But if one only has to double the size of the context to show how verbose comprehensions are, doesn’t that demonstrate the value of <code>map</code> and <code>filter</code>.</p>
</section>
<section id="epilogue" class="level2">
<h2 class="anchored" data-anchor-id="epilogue">Epilogue</h2>
<p>And now a shameless plug of the author’s <a href="https://pypi.org/project/placeholder/">placeholder</a> package for readers who appreciate function-style programming. It provides syntactic sugar for <code>lambda</code>.</p>
<div id="cell-12" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> placeholder <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> _</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>[0, 2, 4, 6, 8]</code></pre>
</div>
</div>
<p>But even speaking as the author, <code>map</code> isn’t the best use case. Sort keys are a much better example, since there is no competing syntax.</p>
<div id="cell-14" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ab'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ba'</span>], key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>_[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>'ba'</code></pre>
</div>
</div>
<p>Python 3.8’s new <a href="https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions">assignment expressions</a> provide yet another alternative.</p>


</section>
</section>

 ]]></description>
  <category>style</category>
  <guid>https://coady.github.io/posts/map-and-filter.html</guid>
  <pubDate>Sat, 31 Mar 2018 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>
