<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Kris Jenkins' Blog</title>
    <link>http://blog.jenkster.com</link>
    <atom:link href="http://blog.jenkster.com/rss.xml" rel="self" type="application/rss+xml" />
    <description>Kris Jenkins' Blog</description>
    <language>en-us</language>
    <pubDate>Fri, 01 Apr 2022 15:05:42 +0100</pubDate>
    <lastBuildDate>Fri, 01 Apr 2022 15:05:42 +0100</lastBuildDate>

    
		<item>
		  <title>MicroServices - Check Size Before Ordering</title>
		  <pubDate>Mon, 09 Jul 2018 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2018/07/microservices-check-size.html</link>
		  <guid>http://blog.jenkster.com/2018/07/microservices-check-size.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;In recent years I’ve seen several startups go for a
microservices-first approach. This is my two cents, distilled from
watching those projects unfold.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re Netflix or Amazon, one of your big problems will be
coordinating different teams and projects. Sooner or later, you’ll
hit a situation where you need to coordinate the release dates of five
different projects to get something major launched.&lt;/p&gt;

&lt;p&gt;On that day, you’re hosed.&lt;/p&gt;

&lt;p&gt;One sub-project will always slip, so five teams sit near-idle for a
month, burning time and money. Fast forward a year or two and you wake
up to six-month drop-dead release cycle with a month-five code-freeze
and a month-four crunch window. It’s horrible. And it never improves,
because coordinating groups of people is &lt;em&gt;hard&lt;/em&gt;. [Citation: Theresa
May, 2016-2018]&lt;/p&gt;

&lt;p&gt;If you’re in that situation, microservices are brilliant. They allow
you to turn a human-coordination problem into a system-coordination
problem. System coordination is still hard - supporting multiple
versions, dealing with concurrency issues, building distributed,
fault-tolerant systems - these are all properly, Computer Science
hard. But they’re tractable.  Computer concurrency problems are a
pain, but you can solve them. People concurrency problems are the
nightmare scenario second only to herd-of-cats concurrency problems.&lt;/p&gt;

&lt;p&gt;Microservices turn people coordination problems into software
coordination problems. Microservices are the way out of a quagmire.&lt;/p&gt;

&lt;p&gt;But what if you don’t have those problems? What if you only have
twenty-odd developers, and you can coordinate just by talking to them?
What if your project coordination problems boil down to, “asking Andy
and Catherine if they’re ready?”  Then by choosing microservices
you’ve created API versioning problems, created concurrency problems
and created distributed, fault-tolerant problems, all for no benefit.&lt;/p&gt;

&lt;p&gt;In the absence of the relevant people problems, microservices &lt;em&gt;create&lt;/em&gt;
software problems. Microservices are the way into a quagmire.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (1/4/22)&lt;/strong&gt; 
Lately I’ve been exposed to a different style of
building microservices which I’m still thinking through. The first
approach - the one I spoke about in this post - looks a lot like a
zoomed-out version of Object Orientation, in which you build systems
that are independent, stateful islands talking to each other through messages.&lt;/p&gt;

&lt;p&gt;The second approach to microservices looks a lot like a zoomed-out
version of Functional Programming, which you build systems that look
like streams of immutable data, with independent transformations on
those streams. I’m still thinking through the implications, and it
deserves a its own new blog post, but for now I’ve put some of my
thinking into this talk: &lt;a href=&quot;https://youtu.be/6LsvrlqLI1g&quot;&gt;Side Effects Are The Complexity
Iceberg&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Emacs Feature Branch Tip</title>
		  <pubDate>Sat, 29 Jul 2017 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2017/07/emacs-feature-branch-tip.html</link>
		  <guid>http://blog.jenkster.com/2017/07/emacs-feature-branch-tip.html</guid>
		  <description>&lt;p&gt;Like many of us, I like to work on feature branches. Branch,
commit-commit-commit, push, pull-request. It’s clean and easy.&lt;/p&gt;

&lt;p&gt;But sometimes I forget a step and screw my workflow up. I get to the
end of a round of commits and realise I forgot to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch&lt;/code&gt; before
I started coding. Now all my work is on local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s fixable, but it’s a pain. You’ve probably been there, and there
are two solutions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create a new branch, stash, reset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin/master&lt;/code&gt;,
checkout the new branch and pop the stash.&lt;/li&gt;
  &lt;li&gt;Or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin master:feature&lt;/code&gt;, and hope that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin/master&lt;/code&gt;
doesn’t move forward before the feature gets merged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The former’s a pain and the latter relies on luck. Neither is ideal.&lt;/p&gt;

&lt;p&gt;Step forward Magit, the premium Emacs git
client. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;magit-branch-spinoff&lt;/code&gt; automatically puts you back where you
want to be. It checks out a new branch based on your current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt;, and
resets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin/master&lt;/code&gt;&lt;sup id=&quot;fnref:docs&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:docs&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. So, so easy.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, it’s available from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x&lt;/code&gt; near you, or from Magit’s
branch menu.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:docs&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;You won’t ben surprised to learn it’s a bit more flexible than that, if you need it to be. See the docs. &lt;a href=&quot;#fnref:docs&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>There's Immutable And Then There's Immutable</title>
		  <pubDate>Wed, 25 Jan 2017 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2017/01/theres-immutable-and-then-theres-immutable.html</link>
		  <guid>http://blog.jenkster.com/2017/01/theres-immutable-and-then-theres-immutable.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;Following a brainwave, a scientist writes something important on a blackboard. Then in large, friendly letters he writes above it, “PLEASE DO NOT ERASE THIS!”&lt;br /&gt;
He leaves the room to grab a coffee.&lt;br /&gt;
Five minutes later he returns, and another scientist is cheerfully
cleaning the blackboard, removing all trace of that world-changing
idea.&lt;br /&gt;
“B-b-but - didn’t you see the note???” yelps the first.&lt;br /&gt;
“The one that said, ‘don’t rub this out?’” replies the second.&lt;br /&gt;
“Yes!”&lt;br /&gt;
“Oh…I thought it meant don’t get rid of the blackboard. I didn’t
realise the contents were important too.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it may be with immutability. Take Scala for instance. Put an object
into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.collection.immutable.List&lt;/code&gt; and the list is guaranteed
never to change. It will always be a one-element list with that object
in it. But the object itself?  No special guarantees there - it’s
still mutable as it was before.&lt;/p&gt;

&lt;p&gt;In this case, the list is the wall and the object is the blackboard -
one is firmly nailed to the other. But just like the blackboard, the
object can change its meaning at will.&lt;/p&gt;

&lt;p&gt;Similarly, in recent JavaScript specs we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.freeze()&lt;/code&gt; which
many will say makes a JavaScript object immutable. And technically it
does - the object’s keys will not change, and the pointers&lt;sup id=&quot;fnref:pointers&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:pointers&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
associated with those keys will not change, but the things they point
to might. JavaScript’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.freeze()&lt;/code&gt; only freezes top-level
properties. In which case it might be better named
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.frosting()&lt;/code&gt;. Again, the blackboard is fixed, but what’s
written on it is a movable feast.&lt;/p&gt;

&lt;p&gt;All this seems odd coming from languages that have immutability as a
core concept, like Clojure &amp;amp; Haskell. In those languages, if I give
you access to my immutable list, you can do anything you like with it
and it won’t affect me. I don’t need to know what you did; I don’t
need to trust you to behave yourself; I can rely on guarantees from
the language itself.
If you try to write on my blackboard, you’ll find yourself transported
to another room, with an identical blackboard that you’re free to do
whatever you like with. Mine remains untouched.&lt;/p&gt;

&lt;p&gt;And so sadly it seems that, like “isomorphic”&lt;sup id=&quot;fnref:isomorphic&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:isomorphic&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;,
“immutable” now has two meanings depending on where you first heard
about it. In the new meaning, you need to know some implementation
details before you can say what part of the data is fixed, and what is
subject to change. That doesn’t sound very immutable to me…&lt;/p&gt;

&lt;p&gt;(I confess I struggle to see the value of immutable frosting. It seems
like, “immutability made easy for the language implementor,” not,
“made valuable for the programmer.”)&lt;/p&gt;

&lt;p&gt;Still, for the record, here’s a definition of immutability that I
think’s unambiguous and useful:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you call a pure function with the same immutable argument, you always get the same result.&lt;sup id=&quot;fnref:river&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:river&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds obvious, but up until a few days ago I thought that was the
only meaningful meaning ‘immutable’ could have…&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:pointers&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m still bothered by JavaScript being a language where there are no C-style pointers, but pointer-based semantics are &lt;em&gt;everywhere&lt;/em&gt;. &lt;a href=&quot;#fnref:pointers&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:isomorphic&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Meaning, “you can convert a value from one type to another and back without losing information,” or, “the same HTML can be rendered on the backend or the frontend.” &lt;a href=&quot;#fnref:isomorphic&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:river&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;You really can cross the same river twice. &lt;a href=&quot;#fnref:river&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Type Bombs in Elm</title>
		  <pubDate>Tue, 08 Nov 2016 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2016/11/type-bombs-in-elm.html</link>
		  <guid>http://blog.jenkster.com/2016/11/type-bombs-in-elm.html</guid>
		  <description>&lt;p&gt;If you want to make anyone on the core Elm team roll their eyes, just
pick a feature that Haskell has and say, “Elm should have it too.”
‘Typeclasses’ is the most common way to play the game, but you’ll get
extra hipster points if you say ‘Higher-Kinded Types’.&lt;/p&gt;

&lt;p&gt;So, I apologise in advance for this post, because it’s a bit, “Haskell
has X, Elm should have X too.” And I’ll try to justify why. But really
this post is about how Elm already has this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$BLESSED_FEATURE&lt;/code&gt;, if you
squint your eyes…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Get to the point Kris - what’s the feature?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Type holes. They’re brilliant. I use them. I should use them
more. At &lt;a href=&quot;http://www.codemesh.io/&quot;&gt;CodeMesh&lt;/a&gt; last week I saw
University Professors popping them like Pez. But crucially for Elm,
they are huge-mongously useful for beginners. They make typed
functional programming easier at every level because they’re all about
getting fast, precise help when you don’t know what to do next.&lt;/p&gt;

&lt;p&gt;Let’s have a quick look at what they are, for the uninitiated, and
then I’ll outline a filthy little trick that gives you type holes in
Elm today.&lt;/p&gt;

&lt;h2 id=&quot;the-hole-truth&quot;&gt;The Hole Truth&lt;/h2&gt;

&lt;p&gt;If you’ve done any programming in Elm (or Haskell, or PureScript, or
…) you’ll know that the compiler always has an opinion on what the
type of a function should be. If you write this function in Elm:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…the compiler knows what this function’s type is, even if you
don’t. And with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--warn&lt;/code&gt; flag, it will happily tell you:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Top-level value &lt;span class=&quot;sb&quot;&gt;`tally`&lt;/span&gt; does not have a type annotation.

67| tally xs =
    ^^^^^
I inferred the type annotation so you can copy it into your code:

tally : List Bool -&amp;gt; ( number, number' )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Maybe you could have figured that type out yourself. But why bother?
The compiler knows about types, and is supposed to be your
assistant. It’s happy to help.&lt;/p&gt;

&lt;p&gt;Type holes use the same mechanism at a more granular level. If the
compiler can assist you in figuring out the type of a function, why
can’t it help you figure out the type of an argument? Why can’t we
say:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;HEY_COMPILER_WHAT_GOES_HERE_MY_FRIEND&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and the compiler would say:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Thank you for asking. I looked at the way the rest of the function
uses that argument, and I think it should have the type:&lt;span class=&quot;sb&quot;&gt;

        `( number, number' )`

&lt;/span&gt;Or somesuch thing. Tally-ho.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you’d say, “Oh yeah, a pair of numbers - that makes sense.” And
your ho would be well and truly tallied.&lt;/p&gt;

&lt;p&gt;Any time you get stuck on what type of argument you need, you can
stick in a marker to the compiler - a type hole - and it gives you its
best guess. It tells you what you’re looking for.&lt;/p&gt;

&lt;p&gt;(Actually, as far as I’ve seen, the experts don’t even wait to get
stuck. They have more holes than Trump’s tax return.)&lt;/p&gt;

&lt;p&gt;Type holes are simple, useful and universal. They save time &amp;amp;
head-scratching. They help.&lt;/p&gt;

&lt;h2 id=&quot;one-more-example&quot;&gt;One More Example&lt;/h2&gt;

&lt;p&gt;Before we get to the Elm-today part, there’s one other place we can
use holes: in the type signature. We’ve already seen that Elm can tell
you the type of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tally&lt;/code&gt; function. But what if we were certain
about &lt;em&gt;part&lt;/em&gt; of the signature? What if we were sure we wanted it to
return a pair of numbers, but weren’t sure what the input type should
be? Type holes to the rescue:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;HEY_COMPILER_WHAT_SAY_YOU_MY_FINE_FELLOW&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Thank you for asking. Of course, I could fill in the whole type
signature, but I appreciate you doing some of the work. The missing
piece looks like a:&lt;span class=&quot;sb&quot;&gt;

    `List Bool`

&lt;/span&gt;...to me. Making the whole signature:

tally : List Bool -&amp;gt; ( number, number' )

Now, why don't you stick that in and make a cup of tea with the time
saved, what?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Having type holes available in the signature makes sense - it means
that whether you’re stuck on the implementation or the design, you can
get some advice.&lt;/p&gt;

&lt;h2 id=&quot;half-a-hole-is-as-good-as-a-whole-one&quot;&gt;Half A Hole Is As Good As A Whole One&lt;/h2&gt;

&lt;p&gt;So that’s type holes. And Elm doesn’t have them. (Yet.) But the point
of this post is not to argue for their inclusion&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. No the point
of this post is, I use type holes in Elm already and I want to tell
you how. It’s a dirty, dirty trick, but it works and only God can
judge me.&lt;/p&gt;

&lt;p&gt;Here’s the secret: To get type holes in Elm, pick a primitive type
&lt;em&gt;that you know is wrong&lt;/em&gt;, and stick that in instead:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;falses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;LOLWAT&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Elm will react with suitable horror:&lt;/p&gt;
&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
74|         )
75|&amp;gt;        &quot;LOLWAT&quot;
76|         xs

Function &lt;span class=&quot;sb&quot;&gt;`foldl`&lt;/span&gt; is expecting the 2nd argument to be:&lt;span class=&quot;sb&quot;&gt;

    ( number, number' )

&lt;/span&gt;But it is:&lt;span class=&quot;sb&quot;&gt;

    String
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There - I stuck in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; knowing it was wrong. Elm borks and
tells me the discrepancy. It says, there’s a conflict between
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;( number, number' )&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;. Since I know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; is wrong,
I now know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;( number, number' )&lt;/code&gt; is right. I have fooled Elm into
giving up the goods.&lt;/p&gt;

&lt;p&gt;Let’s quickly do the same at the type level. I’m unsure of the type of
the first argument, but I’m certain it’s not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Date&lt;/code&gt;, so we’ll use that:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tally&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Elm complains, but in doing so we’ve tricked it into giving us the
right answer:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-- TYPE MISMATCH ---------------------------------------- ./src/Contact/Rest.elm

The type annotation for &lt;span class=&quot;sb&quot;&gt;`tally`&lt;/span&gt; does not match its definition.

67| tally : Date -&amp;gt; ( number, number' )
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The type annotation is saying:&lt;span class=&quot;sb&quot;&gt;

    Date -&amp;gt; ( number, number' )

&lt;/span&gt;But I am inferring that the definition has this type:&lt;span class=&quot;sb&quot;&gt;

    List Bool -&amp;gt; ( number, number' )
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again there’s a disagreement - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Date&lt;/code&gt; isn’t right so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List Bool&lt;/code&gt; must be.&lt;/p&gt;

&lt;p&gt;So that’s it. Stick in a known-wrong answer and it will complain with
the right one.&lt;/p&gt;

&lt;p&gt;In the absence of a proper name I’m calling this trick a Type Bomb,
because if you don’t have a hole, a controlled explosion will do. Go
out there and make some shapes…&lt;/p&gt;

&lt;p&gt;Actually I can’t finish this note without recounting a conversation I had with
&lt;a href=&quot;https://twitter.com/jessitron&quot;&gt;@jessitron&lt;/a&gt; last week:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Me: You know what feature Elm should have?
Jessica: Type holes.
Me: Type hol-. Wait, what did you say?
Jessica: Type holes.
Me: Um, yeah. That.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So she totally stole my thunder, but at least great minds think alike.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m quite certain Evan knows what a type hole is, just as he knows what typeclasses and higher-kinded types are, and he’s either going to put them in or he’s not. I shan’t be telling him what to do. (That said, if Evan happens to be reading, I will say that type holes help beginners as much as experts. More perhaps.) &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Functional Mumbo Jumbo - ADTs</title>
		  <pubDate>Fri, 10 Jun 2016 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2016/06/functional-mumbo-jumbo-adts.html</link>
		  <guid>http://blog.jenkster.com/2016/06/functional-mumbo-jumbo-adts.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;What are “ADTs”?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Algebraic Data Types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lovely. What the heck does that mean?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It means you can mix product and sum types together.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Okay. I have one more question, and please start answering in English: What are product and sum types?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Product types you’ll be deeply familiar with - it’s when you make a
new type by combining others. For example, you could define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;
type as the combination of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; for their name, and an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; for their
age. Like this:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…or like this:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In C that’d be a struct. In Java you’d probably call it a POJO.  In
Clojure they say, “Just use a map.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why’s it called a ‘product’ type?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It might help to think of how many possible values there are for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; now.&lt;/p&gt;

&lt;p&gt;It’s all the possible values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, multiplied by all the
possible values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;. It’s the multiple, or product, of the two
types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Okay, product types combine types together. What’s a sum type?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, product types are a bit like an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AND&lt;/code&gt; operation, aren’t they?
They &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AND&lt;/code&gt; types together. If you think of it that way, you’re
instantly going to start to wonder what an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OR&lt;/code&gt; would look like. For
that, we can pull out another old chestnut from the Big Book of Type
Examples. Chapter two, playing cards:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Suit&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Heart&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Spade&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Club&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Diamond&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A suit is a heart, or a spade, or a club, or a diamond. Any one of
those four values, but only one. It’s an exclusive-or, as a type.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So a sum type is just an enum?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well…yeah I suppose it is. But that’s not what makes this
interesting. An ADT isn’t just structs and enums, it’s the &lt;em&gt;free mixing
of them&lt;/em&gt; to make sophisticated data models.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Give me a concrete example.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Glad you asked. I’m going to make a credit card payment. When the
answer comes back from my payment provider, there are lots of things
that could happen. Hopefully it goes well and I get a receipt ID back
as a string. But maybe the card on file has expired, and I get a few
details about the card to prompt the user with. Or it just blows up with
different kinds of error. I can model all possible responses neatly
with an ADT, like so:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PaymentResponse&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Paid&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CardExpired&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;HttpError&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AuthError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Paid&lt;/code&gt;, which is a wrapper around a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CardExpired&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HttpError&lt;/code&gt; which are product types; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthError&lt;/code&gt;
which is a “traditional” enum value. All mixed together in a sum type
to model all possible payment responses.&lt;/p&gt;

&lt;p&gt;Most languages don’t have support for this. They might have enums, but
not ones that carry data. You can’t have an enum of structs
or an enum of POJOs&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Clojure’s an interesting case where it does have ADTs, but they’re
possibly too flexible. You can mix together maps, lists and primitives
to make any shape of data you like. But you can suffer with the
exclusion problem. While you can say all these things are valid
responses:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:paid&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;eefa9112&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:card-expired&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8783&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;03/19&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:http-error&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Server just exploded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:auth-error&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…you have a harder time saying what &lt;em&gt;isn’t&lt;/em&gt; a valid response, like:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:card-expired&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;we don't know why&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s where Plumatic schema and spec become essential.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So is that it? Is that all an ADT is?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No. You’re at the entrance to a delightful rabbit hole. ADTs can have
type variables, and can be further generalised, and all sorts of
useful stuff. But if you have the core idea - mixing and matching ANDs
and ORs to build up data models - you’re on your way.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So why is it useful?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because data-modelling is the most important thing we do, so tools for
modelling data are fundamentally interesting. But let me give you a
concrete example of something cool to go away with. Once we’ve defined
our rich data type, a suitably-savvy compiler will be able to help us
use it properly. Here’s some pseudo-code to handle payment responses:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;paymentResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;paymentResponse&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Paid&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;receipts&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;CardExpired&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fourDigits&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;notifyUser&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Your card &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fourDigits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; expired on &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;HttpError&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;logError&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Did you spot the error in that code? You probably did, but the
compiler is guaranteed to notice:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; MISSING PATTERNS &lt;span class=&quot;nt&quot;&gt;----------------------------------------------&lt;/span&gt; src/Main.elm

This &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; does not have branches &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;all possibilities.

...

You need to account &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the following values:

    PaymentResponse.AuthError

Add a branch to cover this pattern!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The compiler knows which values &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PaymentResponse&lt;/code&gt; can have, and so can check our case
statements for completeness. In this case, it’s instantly noticed that
we’ve ignored the authorization failure.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sweet. Okay, last question. If there’s AND and OR…where’s NOT?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You mean a type that can be any type &lt;em&gt;except&lt;/em&gt; something?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yeah.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Interesting question. Yup, that’d still be part of an Algebra of Data
Types, so it’d count. I’ve never seen it though. Let me know if you do…&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And nearly every language has a way to get around it. In Java you’d use reflection on subclasses, perhaps. But first-class support? No. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>How Elm Slays a UI Antipattern</title>
		  <pubDate>Fri, 03 Jun 2016 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html</link>
		  <guid>http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html</guid>
		  <description>&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;There’s a bug in several places in the OSX Twitter client, and in at
least one place in the Slack client, and in &lt;em&gt;loads&lt;/em&gt; of other
apps. Here’s Twitter:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/twitter_zero.png&quot; alt=&quot;Twitter says no&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s not the correct data. When I go to this tweet, it shows “0
Retweets 0 Likes” for a few moments, until the real data loads in.&lt;/p&gt;

&lt;p&gt;Now here’s Slack:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/slack_zero.png&quot; alt=&quot;Slack says no&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Again, it’s not correct. when I go to the view it says, “no messages,”
as a placeholder until the actual data loads in. A few moments later
I get a big long list.&lt;/p&gt;

&lt;p&gt;It’s one of those UX patterns that crops up everywhere once you start
noticing it: showing zero or empty when you should be showing a
loading message.  It’s incredibly common.&lt;/p&gt;

&lt;p&gt;Now I don’t have access to their source code, of course, but I’m
willing to bet that in most cases, it boils down to this broken data
model:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Store a loading flag and an empty list/count of things you’re loading.
Then in the UI, you’re supposed to check the loading flag before you
display the things.&lt;/p&gt;

&lt;p&gt;Inevitably someone forgets, and so on a slow connection the UI
immediately displays the, “No Things Found,” message until the
response comes back.&lt;/p&gt;

&lt;p&gt;We’ve all done it. Especially when deadlines are tight and people
start planning whole sprints around, “the happy path.” But it’s poor
UX, and it’s a shame to spoil a quality experience on such a small
detail.&lt;/p&gt;

&lt;p&gt;Now, how can we fix this? Discipline? Linters? More unit tests? A QA
army?  No! Let’s fix the data model, because fixing the data model is
fastest, cheapest, most reliable fix there is.&lt;/p&gt;

&lt;h2 id=&quot;to-elm&quot;&gt;To Elm!&lt;/h2&gt;

&lt;p&gt;Let’s move over to Elm, because we’ll need a language with explicit
data models if we’re going to talk about this properly. So here’s an
absolutely basic version of this data model, and it’s a wrong ‘un:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Thing&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you think about it, this broken from the outset.  It’s saying that you
will always have a list of things available, which isn’t true when we
startup. And that causes the display bug.&lt;/p&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;

&lt;p&gt;A much better model would be:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can represent, “we haven’t loaded things yet,” naturally. On
startup the list of things is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Nothing&lt;/code&gt;. When the load completes it
becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just [thing1, thing2, ...]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the server replies that there genuinely were no things, then that’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just []&lt;/code&gt;. Now the empty list actually means the empty list, it’s no
longer doing double-duty as the “not loaded” case.&lt;/p&gt;

&lt;p&gt;You can do this in JavaScript of course, but you won’t. Long
experience will have taught you that setting a property to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; may
be correct, but it’s just asking for runtime exceptions. Hence the
separate loading flag, which gets forgotten.&lt;/p&gt;

&lt;p&gt;In Elm, you can not only handle the nothing case safely, but the
compiler will actively nag you to remember to write the “Loading”
message:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;someView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and when we compile:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; MISSING PATTERNS &lt;span class=&quot;nt&quot;&gt;----------------------------------------------&lt;/span&gt; src/View.elm

This &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; does not have branches &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;all possibilities.

...

You need to account &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the following values:

    Maybe.Nothing

Add a branch to cover this pattern!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We get an error message about missing out the loading case, &lt;em&gt;exactly&lt;/em&gt;
where the solution needs to go.&lt;/p&gt;

&lt;p&gt;On the surface it seems like we’ve made a simple data-model change,
but by reshaping the data it becomes &lt;em&gt;much&lt;/em&gt; easier to ensure an
improved user experience. Win.&lt;/p&gt;

&lt;h2 id=&quot;the-leveling-up&quot;&gt;The Leveling-Up&lt;/h2&gt;

&lt;p&gt;I like this, but I reckon we can be much more sophisticated. And Elm
will still make it easy when we do. In my mental model, REST requests
have one of four states:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We haven’t asked yet.&lt;/li&gt;
  &lt;li&gt;We’ve asked, but we haven’t got a response yet.&lt;/li&gt;
  &lt;li&gt;We got a response, but it was an error.&lt;/li&gt;
  &lt;li&gt;We got a response, and it was the data we wanted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a language with nice data-modelling facilities, we can easily create
something that represents these four states:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RemoteData&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NotAsked&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Loading&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Failure&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Success&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt; type, where we can have parameters
for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Failure&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Success&lt;/code&gt; types, plus tracking for the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotAsked&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Loading&lt;/code&gt; states.&lt;/p&gt;

&lt;p&gt;Now in our data model, we can properly represent the list of things as
something we fetch from an external source:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RemoteData&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s make a quick refinement to that - most of our external requests
are REST requests, so the error type is nearly always an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Http.Error&lt;/code&gt;. A quick alias tidies that up:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;WebData&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;RemoteData&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;


  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;WebData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The nice thing about this data model in Elm is, the compiler will now
force you to write the correct UI code. It will keep track of the
possibility of “things not loaded” and errors, and &lt;em&gt;force&lt;/em&gt; you to
handle them all in the UI.&lt;/p&gt;

&lt;p&gt;Personally, I love it. A bit of thought about the data model, a couple
of utterly-reusable definitions, and for the rest of the project the
compiler will be at our backs, pushing us towards better UX. Happier
users at bargain prices.&lt;/p&gt;

&lt;h2 id=&quot;the-download&quot;&gt;The Download&lt;/h2&gt;

&lt;p&gt;If you want to play with this, I’ve published it as a standalone
package which you can add to your project with:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;elm package &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;krisajenkins/remotedata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://package.elm-lang.org/packages/krisajenkins/remotedata/latest&quot;&gt;Here are the docs&lt;/a&gt;, and happy modelling!&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Clojure-Fu with Juxt</title>
		  <pubDate>Wed, 01 Jun 2016 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2016/06/clojure-fu-with-juxt.html</link>
		  <guid>http://blog.jenkster.com/2016/06/clojure-fu-with-juxt.html</guid>
		  <description>&lt;p&gt;I love &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;juxt&lt;/code&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. But I was reminded yesterday that not everyone
has made friends with it. So, to give it a little of the limelight it
deserves, I thought I’d write down My Favourite Juxt Trick.&lt;/p&gt;

&lt;h2 id=&quot;the-recap&quot;&gt;The Recap&lt;/h2&gt;

&lt;p&gt;First, let’s recap what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;juxt&lt;/code&gt; does: it lets you pass the same
arguments to several functions in a row. So if you want to find out a
person’s name &amp;amp; height, you can do this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name-and-height&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;juxt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name-and-height&lt;/code&gt; is now a single function that returns both results
as in a vector:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Kris&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:height&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;172&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:devastating-handsomeness-factor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name-and-height&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;;=&amp;gt; [Kris 172]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nothing special there. It’s just calling each function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:name&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:height&lt;/code&gt;, with the same arguments, and gathering up the results.&lt;/p&gt;

&lt;h2 id=&quot;the-trick&quot;&gt;The Trick&lt;/h2&gt;

&lt;p&gt;Now let’s do something cool with it. I’ve got a list of people working
in different departments:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Brad&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hats&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Janet&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;54000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;capes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Eddie&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19500&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hats&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Frank&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;98000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;capes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Rocky&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shoes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’d like to roll those up by department and largesse. First let’s
define what counts as highly-paid, using a number that’s entirely
fictional in London:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highly-paid?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:salary&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we have two functions, and we can group by both of them:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group-by&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;juxt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:department&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highly-paid?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code class=&quot;language-edn&quot;&gt;{[&quot;hats&quot; false]
 [{:name &quot;Brad&quot;, :salary 27000, :department &quot;hats&quot;}
  {:name &quot;Eddie&quot;, :salary 19500, :department &quot;hats&quot;}],
 [&quot;capes&quot; true]
 [{:name &quot;Janet&quot;, :salary 54000, :department &quot;capes&quot;}
  {:name &quot;Frank&quot;, :salary 98000, :department &quot;capes&quot;}],
 [&quot;shoes&quot; false] [{:name &quot;Rocky&quot;, :salary 18000, :department &quot;shoes&quot;}]}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There - we’ve just built an on-the-fly, composite-key index of our
data, for free.&lt;/p&gt;

&lt;p&gt;Any time you need to filter some data by multiple criteria, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;juxt&lt;/code&gt;
comes in mighty handy.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Sorry &lt;a href=&quot;https://juxt.pro/&quot;&gt;Juxt&lt;/a&gt;. I love you too, but this one is about your namesake. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>How I Structure Elm Apps</title>
		  <pubDate>Sat, 16 Apr 2016 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html</link>
		  <guid>http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;Updated: 1st Aug 2016 for Elm 0.17.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the rise of people getting to grips with Elm, I’m hear several
folks wondering how to make the transition from play project to a
larger app. So, in the hope that it helps ease that transition, here’s
my guide to structuring large Elm apps. Follow along and you should
have an easier time.&lt;/p&gt;

&lt;h2 id=&quot;startup&quot;&gt;Startup&lt;/h2&gt;
&lt;p&gt;First, there are two packages that begin every Elm app, so
let’s install them:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;elm package &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--yes&lt;/span&gt; elm-lang/core
elm package &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--yes&lt;/span&gt; elm-lang/html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then I’ll edit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elm-package.json&lt;/code&gt; file that’s just been created
and set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source-directories&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;source-directories&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that in place, we can talk about file structure. There’s one
special file, and a then a pattern that repeats throughout the app.&lt;/p&gt;

&lt;h3 id=&quot;srcappelm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/App.elm&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The special file is the app’s entry point. I typically call it
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/App.elm&lt;/code&gt;, though some choose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/Main.elm&lt;/code&gt;. If you were building
several different Elm apps from the same code base, I might name the
entry points more specifically, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/Public.elm&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/Admin.elm&lt;/code&gt;. But for now, let’s just talk about a single entry point.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App&lt;/code&gt; contains as little as possible to get the app started, which is
usually just:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;program&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initialState&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rootView&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code is pretty much lifted from the docs. The only
difference is this is /all/ just wiring. The real code has been moved
out into a repeating pattern of four files.&lt;/p&gt;

&lt;h2 id=&quot;the-featureful-four&quot;&gt;The Featureful Four&lt;/h2&gt;

&lt;p&gt;Every feature, subfeature, page, widget and gizmo will have its own
directory, and in that directory there will almost certainly be
these four files:&lt;/p&gt;

&lt;h3 id=&quot;featuretypeselm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.../feature/Types.elm&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Types&lt;/code&gt; houses the type definitions for this feature. At a
minimum, it will contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Msg&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…plus any other types that are unique to this feature.&lt;/p&gt;

&lt;p&gt;It will also house generic functions on those types. Not application
logic, but library functions to make working with those types easier.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Types&lt;/code&gt; will typically export everything, and use anything from
subfeatures’ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Types&lt;/code&gt;, so the top of the file will look like:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;featurestateelm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.../feature/State.elm&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;This is the brain of each feature. Shaped by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Html.App&lt;/code&gt;, this will
contain a minimum of three declarations, The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subscriptions&lt;/code&gt; functions. First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cmd&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is what must be set up to start using this feature. Any parent
that makes use of this feature agrees to pull this in when it starts
using it.&lt;/p&gt;

&lt;p&gt;It’s perfectly fine for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; to be a function instead of a
value. For example, you might have a reservation widget that expires
after 15 minutes, so needs to know its startup time:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cmd&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;startTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the starting state in place, next we need the update function:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cmd&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the function that reacts to events, triggers external effects
and steps the the app forward in time. If you’re changing or debugging
application logic, you’ll start working here.&lt;/p&gt;

&lt;p&gt;Last we need subscriptions, which may be as simple as:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or may actually do its own work:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;Websocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ws://echo.websocket.org&quot;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Echo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or even mix in the subscriptions of children:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Sub&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Websocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ws://echo.websocket.org&quot;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Echo&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Child&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sub&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ChildMsg&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;State&lt;/code&gt; will usually just export these three key components, and
will expect them of its sub-components:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;featureviewelm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.../feature/View.elm&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View&lt;/code&gt; contains rendering code. Things with the type signature
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;... -&amp;gt; Html Msg&lt;/code&gt;, and rarely anything else. I name the entry point
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View&lt;/code&gt; will usually only export &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;, and will use subfeatures’
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Types&lt;/code&gt; model &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View.root&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;grommitList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grommits&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GrommitMsg&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;featurerestelm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.../feature/Rest.elm&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Last is RESTful code (HTTP and JSON-handling), which I name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rest&lt;/code&gt;.
Not every feature needs such code, of course, but it’s so common that
it’s worth describing.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rest&lt;/code&gt; namespace contains HTTP calls, and JSON encoders/decoders,
and little else.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rest&lt;/code&gt; will usually export everything, and may use subfeatures’
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Types&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rest&lt;/code&gt; modules:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Rest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Rest&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Grommit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Rest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap Up&lt;/h2&gt;

&lt;p&gt;Along with the top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.elm&lt;/code&gt;, that pattern-of-four describes the
vast majority of my directories in all of my Elm projects. As a layout
it works well. The pattern makes everything easier to find and modify,
as it answers a lot of useful questions without thinking:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Q. Where’s the code for registration?&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A. Look for a directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Registration&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Where’s the code for feature X?&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A. Look for a directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. X doesn’t look right.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A. Look in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X/View.elm&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. X doesn’t behave right.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A. Look in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X/State.elm&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. X needs a new feature.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A. Start by changing the data-model in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X/Types.elm&lt;/code&gt;, and then follow the compiler messages through.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Our API is changing.&lt;/li&gt;
  &lt;li&gt;A. Start by changing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X/Rest.elm&lt;/code&gt;, and then follow the compiler messages through.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s very little surprise and a good default organization. The
really nice thing about it is that it works recursively. You can use
this layout in every feature and sub-feature and sub-sub-features.&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src
├── App.elm
├── Types.elm
├── State.elm
├── View.elm
├── FrontPage
│   ├── Rest.elm
│   ├── State.elm
│   ├── Types.elm
│   └── View.elm
├── Login
│   ├── Rest.elm
│   ├── State.elm
│   ├── Types.elm
│   └── View.elm
└── Registration
    ├── Rest.elm
    ├── State.elm
    ├── Types.elm
    └── View.elm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;/h2&gt;

&lt;p&gt;Take this pattern as a default, and remember to think for yourself. In
my codebases you’ll find features that are so tiny that I occasionally
stick the whole thing in one file. (Not often, but sometimes.)  And
you’ll certainly files other than these four, for special
use-cases. But this simple approach covers a lot of ground, neatly.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Git for Static Sites</title>
		  <pubDate>Tue, 09 Feb 2016 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2016/02/git-for-static-sites.html</link>
		  <guid>http://blog.jenkster.com/2016/02/git-for-static-sites.html</guid>
		  <description>&lt;p&gt;I often find myself creating static websites, where I want to push the
source to Github, and publish the result somewhere, quickly and
cheaply.&lt;/p&gt;

&lt;p&gt;One example is presentations, which I write in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-mode&lt;/code&gt; and then
publish using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reveal.js&lt;/code&gt;. Another is Elm sites, when I build the site
in Elm and need to host the generated HTML/JavaScript, without
necessarily wanting a custom backend.&lt;/p&gt;

&lt;p&gt;So, here’s how I do it. Follow along and you’ll learn a practical
trick for publishing, and some &lt;em&gt;git-fu&lt;/em&gt; to boot…&lt;/p&gt;

&lt;h2 id=&quot;publish-on-github&quot;&gt;Publish on Github&lt;/h2&gt;

&lt;p&gt;The first thing to know is that those generous souls at Github will
publish your static sites for free. If you create any repo with a
branch called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt;, they’ll publish it that branch on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;your-username&amp;gt;.github.io/&amp;lt;repo-name&amp;gt;&lt;/code&gt; a few minutes later.&lt;/p&gt;

&lt;p&gt;So you could just create a brand new repository, commit your
compiled-down site to it, and rename &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That would do the job, but we can improve things.&lt;/p&gt;

&lt;h2 id=&quot;orphan-branches&quot;&gt;Orphan Branches&lt;/h2&gt;

&lt;p&gt;Keeping two separate-but-related repos, one for the source and one for
the output, gets old quickly. Especially for small projects.  Ideally
I’d like two separate project trees managed in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt;
directory, to keep everything together.  And there’s something that
feels &lt;em&gt;correct&lt;/em&gt; about managing the two facets of the project in one
place. Doing exactly that is very easy:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout &lt;span class=&quot;nt&quot;&gt;--orphan&lt;/span&gt; gh-pages
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you checkout an ‘orphan’ branch, git creates an entirely new
branch without any parent commits (hence the name, ‘orphan’). You can
add anything you want to that branch, and it’s separate from the main
history, but stored in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;After creating an orphan branch you can clear out the current
directory - safe in the knowledge that it’s all still saved on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; - and add any new content you want. The orphan branch has its
own timeline and own files, but it’s housed within the same git repo.&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push -u origin gh-pages&lt;/code&gt; the first time you want
to push, and from then on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; will send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;, publishing
your source, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt;, publishing your site.&lt;/p&gt;

&lt;p&gt;We just need one more piece to make this work really smoothly.&lt;/p&gt;

&lt;h2 id=&quot;worktrees&quot;&gt;Worktrees&lt;/h2&gt;

&lt;p&gt;The only problem with the orphan branch approach is that the workflow
typically goes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Checkout &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Build the site to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dist&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Checkout &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Copy the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dist&lt;/code&gt; up to the top level.&lt;/li&gt;
  &lt;li&gt;Commit and push.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s fine, but the file-copying is a little unwieldy. The the
solution, that makes this whole approach flow smoothly, is using git
worktrees - a new feature in git 2.5.&lt;/p&gt;

&lt;p&gt;With worktrees, you can have two completely separate working
directories, backed by the same git repo.  It’s a feature I use when I
want to flip between active-branches without stashing all the time.
(For example, when you’re blocked halfway through feature A, so you
want to crack on with feature B, but you know you’ll need to flip back
and forth.)&lt;/p&gt;

&lt;p&gt;For our purposes though, worktrees allow us to build directly to our
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; branch. We start a worktree off like so:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;
/.../my-project
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git worktree add ../my-project-dist gh-pages
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we have two directories side-by-side:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; - /my-project       &lt;span class=&quot;c&quot;&gt;# Checked out as master&lt;/span&gt;
|
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; - /my-project-dist  &lt;span class=&quot;c&quot;&gt;# Checked out as gh-pages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we just alter our build script to build into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;../my-project-dist&lt;/code&gt;
and the setup’s complete. Any commits in either directory get stored
on the same repo. And pushes, pulls or fetches will synchronise
exactly as you’d hope.&lt;/p&gt;

&lt;h2 id=&quot;to-recap&quot;&gt;To Recap&lt;/h2&gt;

&lt;h3 id=&quot;why&quot;&gt;Why?&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;You want to manage a source and a release repo.&lt;/li&gt;
  &lt;li&gt;With easy publishing of the release repo.&lt;/li&gt;
  &lt;li&gt;With the minimum of admin.&lt;/li&gt;
  &lt;li&gt;With a guarantee that if you’ve got one, you’ve got the other.&lt;/li&gt;
  &lt;li&gt;With a guarantee that if you’ve backed-up one, you’ve backed-up the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how&quot;&gt;How&lt;/h3&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create the orphan gh-pages branch&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout &lt;span class=&quot;nt&quot;&gt;--orphan&lt;/span&gt; gh-pages

&lt;span class=&quot;c&quot;&gt;# Create at least one commit.&lt;/span&gt;
...

&lt;span class=&quot;c&quot;&gt;# Connect local gh-pages to the remote version.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; origin gh-pages

&lt;span class=&quot;c&quot;&gt;# Head back to master.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout master

&lt;span class=&quot;c&quot;&gt;# Check out the the orphan gh-pages branch in its own directory.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git worktree add ../my-project-dist gh-pages


&lt;span class=&quot;c&quot;&gt;# Finally, from now on, to publish both the source and the release it's just.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Which Programming Languages Are Functional?</title>
		  <pubDate>Tue, 29 Dec 2015 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2015/12/which-programming-languages-are-functional.html</link>
		  <guid>http://blog.jenkster.com/2015/12/which-programming-languages-are-functional.html</guid>
		  <description>&lt;p&gt;&lt;a href=&quot;/2015/12/what-is-functional-programming.html&quot;&gt;In part one of this post&lt;/a&gt;, I defined functional programming not from an
academic perspective, or a marketing one, but in a way that will make
sense to a jobbing programmer. More importantly, I hope, I defined
what side-effects are in a way that makes it easy for a jobbing
programmer to spot them before they spiral out of control.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at functional programming languages in the real
world…&lt;/p&gt;

&lt;h2 id=&quot;pot-shots-across-the-programming-landscape&quot;&gt;Pot Shots Across the Programming Landscape&lt;/h2&gt;

&lt;p&gt;Armed with the ability to spot side-effects, we can now look at a
given function and spot hidden complexity. And armed with some
real-world definitions of FP, we can now survey the programming world
and fire some new insights in practically every direction…&lt;/p&gt;

&lt;h3 id=&quot;functional-programming-is-not&quot;&gt;Functional Programming is not…&lt;/h3&gt;

&lt;h4 id=&quot;its-not-map-and-reduce&quot;&gt;It’s not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Even though you’ll see these functions in every functional language,
it’s not what makes the language functional. It’s just something that
crops up nearly every time you try to take the side-effects out of
processing sequences of things.&lt;/p&gt;

&lt;h4 id=&quot;its-not-lambda-functions&quot;&gt;It’s not lambda functions&lt;/h4&gt;

&lt;p&gt;Again, you’ll probably see first-class functions in every FP
language. But it’s something that naturally emerges when you start
building a language that avoids side-effects. It’s an enabler, but not
the root cause.&lt;/p&gt;

&lt;h4 id=&quot;its-not-types&quot;&gt;It’s not types&lt;/h4&gt;

&lt;p&gt;Static type checking is a very useful tool, but it’s not a
pre-requisite for FP. Lisp is the oldest functional programming
language, and the oldest dynamic language.&lt;/p&gt;

&lt;p&gt;Static types can be very useful though. Haskell uses its type system
beautifully in the attack on side-effects. But they aren’t the
ingredient that makes or breaks a functional language.&lt;/p&gt;

&lt;p&gt;Say it long, say it loud, functional programming is about side-effects.&lt;/p&gt;

&lt;p&gt;(And side-causes, of course).&lt;/p&gt;

&lt;h2 id=&quot;what-does-this-mean-for-languages&quot;&gt;What Does This Mean For Languages?&lt;/h2&gt;

&lt;h3 id=&quot;javascript-is-not-a-functional-programming-language&quot;&gt;JavaScript is not a Functional Programming Language&lt;/h3&gt;

&lt;p&gt;Functional languages help you eliminate side-effects where you can,
and control them where you can’t. JavaScript doesn’t meet this
criteria. In fact, it’s easy to spot places where JavaScript actively
&lt;em&gt;encourages&lt;/em&gt; side-effects.&lt;/p&gt;

&lt;p&gt;The easiest target is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt;. The hidden input that’s in every
function. What’s particularly magical about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; is how freely its
meaning changes. Even expert JavaScript programmers have trouble
keeping track of what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; currently refers to. From a functional
point of view, the fact that it’s magically available at all is a
design smell.&lt;/p&gt;

&lt;p&gt;While you can certainly load FP &lt;em&gt;libraries&lt;/em&gt; (Immutable.js, for
instance) into JavaScript, and that makes programming in a functional
style easier, it doesn’t change the nature of the language itself.&lt;/p&gt;

&lt;p&gt;(By the way, if you like the functional libraries that are gaining
popularity in JavaScript land, imagine how much you’d like a whole
language that supported the functional style.)&lt;/p&gt;

&lt;h3 id=&quot;java-is-not-a-functional-programming-language&quot;&gt;Java is not a Functional Programming Language&lt;/h3&gt;

&lt;p&gt;Java is most definitely not a functional language. The addition of
lambdas in Java 1.8 does nothing to change that. Java stands in stark
opposition to functional programming. It’s core design principal says
that code should be organised as a series of localised side-effects -
methods that depend on and change the local state of an object.&lt;/p&gt;

&lt;p&gt;In fact, Java is hostile to functional programming. If you write Java
code that has no side-effects, that doesn’t read or change the local
object’s state, you’ll be called a Bad Programmer. That’s not how Java
is written. Your side-effect free code will be peppered with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt;
keywords, and they’ll frown and drive you out of town.&lt;/p&gt;

&lt;p&gt;I’m not saying Java is wrong. (Well, okay, I am.) But the point is it
takes a completely different view of side-effects.  Java thinks that
localised side-effects are cornerstone of good code; FP thinks they’re
the devil.&lt;/p&gt;

&lt;p&gt;You could look at that from a slightly different angle. You could see
both Java and FP as responses to the problem of side-effects. Both
models recognise side-effects as a problem, and respond
differently. OO’s answer is, “contain them within boundaries called
‘objects’,” whereas FP’s answer is, “eliminate them”. Unfortunately,
in practice Java doesn’t just try to encapsulate side-effects; it
mandates them. If you’re not creating side-effects, in the form of
stateful objects, then you’re a Bad Java Programmer. People actually
get fired for writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; too often.&lt;/p&gt;

&lt;h3 id=&quot;scala-has-a-big-task-on-its-hands&quot;&gt;Scala Has a Big Task on its Hands&lt;/h3&gt;

&lt;p&gt;Seen in this light, Scala is a very challenging proposition. If its
goal is to unify the two worlds of OO and FP, then through the lens of
side-effects we see it as trying to bridge the gap between
“Side-Effects Mandatory” and “Side-Effects Forbidden&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;”. They’re
such opposite views that I’m not sure they can be reconciled. You
certainly can’t unify the two just by making objects support the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;
function. You’ll need to go deeper and reconcile the conflict between
the two opposing stances on side-effects.&lt;/p&gt;

&lt;p&gt;I’ll leave you to judge if Scala succeeds in such a
reconciliation. But if I were in charge of Scala’s marketing I’d sell
it as a &lt;em&gt;gradual&lt;/em&gt; move away from the side-effecting world of Java, to
the pure world of FP. Instead of unifying them, it could be a bridge
away. Indeed, many people see it that way in practice.&lt;/p&gt;

&lt;h3 id=&quot;clojure&quot;&gt;Clojure&lt;/h3&gt;

&lt;p&gt;Clojure takes an interesting stance on side-effects. Its creator, Rich
Hickey, has said that Clojure is about “80% functional”. I think I can
clarify why that is. From the outset, Clojure was designed to deal
with one specific kind of side-effect: Time.&lt;/p&gt;

&lt;p&gt;To illustrate this, here’s a Java joke for you:&lt;/p&gt;

&lt;p&gt;#+BEGIN_QUOTE&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;What’s 5 plus 2?&lt;/li&gt;
  &lt;li&gt;7.&lt;/li&gt;
  &lt;li&gt;Correct. What’s 5 plus 3?&lt;/li&gt;
  &lt;li&gt;8&lt;/li&gt;
  &lt;li&gt;Nope. It’s 10, because we turned 5 into 7, remember?
#+END_QUOTE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, it’s not a great joke. But the point is, in Javaland, values
don’t stay still. We might legitimately take something that represents
a five, call a function, and find that it’s no longer a
five. Mathematics says that five never changes - we can call a
function that gives us a &lt;em&gt;new&lt;/em&gt; value, but we can never affect the
nature of five itself. Java says values change all the time, and as
long as they’re wrapped in object boundaries that’s okay.&lt;/p&gt;

&lt;p&gt;The integer case may seem trivial, but the effect is amplified when we
look at larger values. Remember &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt; from &lt;a href=&quot;/2015/12/what-is-functional-programming.html&quot;&gt;part 1&lt;/a&gt;? The state of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt; is a value that changes over time. We can say that Time
is a side-cause to the meaning of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Clojure focuses ferociously on the side-cause of Time. Rich Hickey’s
insight&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; is that the hidden effect of time means we can’t rely on
values to stay put; and if we can’t rely on that, we can’t rely on our
functions’ inputs, and so we can’t rely on anything to behave
predictably or repeatably. If even values have side-effects, then
&lt;em&gt;everything&lt;/em&gt; has side-effects. If values aren’t pure, nothing in our
programs can be pure.&lt;/p&gt;

&lt;p&gt;So Clojure takes a sword to time. All its values are immutable
(unchanging over time) by default. If you need a changing value,
Clojure provides wrappers around unchanging values, and those wrappers
are subject to heavy constraints:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You must opt-in to changing (mutable) values by using a wrapper.&lt;/li&gt;
  &lt;li&gt;You cannot &lt;em&gt;accidentally&lt;/em&gt; create a mutable value. You must always use
guards in the language explicitly flag potential side-effects.&lt;/li&gt;
  &lt;li&gt;You cannot unwittingly consume a mutable-value. You must always use
guards in the language explicitly acknowledge the risk of
side-effects.&lt;/li&gt;
  &lt;li&gt;When you open a mutable-value wrapper, the thing you get back is
immutable again. You can easily get back out of the time-dependent
world and back into the pure one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;With respect to time&lt;/em&gt;, Clojure is a great example of a functional
programming language. The language is deeply hostile to the
side-effect of time. It eliminates it wherever it can, by default, and
where you feel you must have the side-effect, it helps you tightly
control it so it doesn’t spill into the rest of your program.&lt;/p&gt;

&lt;h3 id=&quot;haskell&quot;&gt;Haskell&lt;/h3&gt;

&lt;p&gt;If Clojure is hostile to time, Haskell is just plain hostile. Haskell
really hates side-effects, and puts a large amount of effort into
controlling them.&lt;/p&gt;

&lt;p&gt;One of the interesting ways Haskell fights side-effects is with
types. It pushes all side-effects up into the type-system. For
example, imagine you’ve got a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getPerson&lt;/code&gt; function. In Haskell it
might look like:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;getPerson&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can read that as, “takes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UUID&lt;/code&gt; and returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; &lt;em&gt;in the
context of&lt;/em&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Database&lt;/code&gt;”. This is interesting - you can look at the
type signature of a Haskell function and know for certain which
side-effects are involved. And which aren’t. You can also make
guarantees like, “this function won’t access the filesystem, because
it’s not declared that kind of side-effect.” Tight control&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Equally important, you can look at a function like:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;formatName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and know that this just takes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; and returns a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;. Nothing else, because if there were side-effects you’d see
them locked into the type signature.&lt;/p&gt;

&lt;p&gt;But perhaps most interesting of all, is this example:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;formatName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The signature tells us that this version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;formatName&lt;/code&gt; involves
database-related side-effects. What the hell? Why does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;formatName&lt;/code&gt;
need the database?  You mean I’m going to need to set-up and mock-out
a database just to test a name-formatter? That’s really weird.&lt;/p&gt;

&lt;p&gt;Just by looking at this function signature, I can see something’s
wrong with the design. I don’t need to look at the code, I can smell a
rat just from the overview. That’s magic.&lt;/p&gt;

&lt;p&gt;Let’s just briefly compare that with the Java signature:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;formatName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{..}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which Haskell-version is that equivalent to? Without seeing the body
of the function, you have no way of knowing. It may be the pure
version, it may access the database. Or it may delete the filesystem
and return, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;screw you boss!&quot;&lt;/code&gt;. The type signature tells you very
little about what’s going on, or what the surface area of the function
is.&lt;/p&gt;

&lt;p&gt;Haskell’s type signatures, in contrast, tell you a great deal about
the design. And because they’re checked by the compiler, they tell you
things you &lt;em&gt;know&lt;/em&gt; to be true. And that means they make great
architectural tools. They surface design-smells at a very high level,
And they also surface patterns of coding too. I’m going to keep the
words ‘functor’ and ‘monad’ out of this post, but I will say that
high-level software patterns begin with high-level analysis, and
high-level analysis is made &lt;em&gt;much&lt;/em&gt; easier when you have a high-level
&lt;em&gt;notation&lt;/em&gt;&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id=&quot;perl&quot;&gt;Perl&lt;/h3&gt;

&lt;p&gt;Perl deserves a mention here in any discussion of side-effects. It has
a magic argument, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_&lt;/code&gt;, which means something like, “the return value
of the previous call&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.”  It gets used and/or changed by many of
the core library functions, implicitly. As far as I know this gives
Perl the distinction of being the only language where one global
side-effect is considered a core feature.&lt;/p&gt;

&lt;h3 id=&quot;python&quot;&gt;Python&lt;/h3&gt;

&lt;p&gt;Let’s take a quick look at a fundamental side-effecting pattern in Java:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How would we purify this call? Well, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; is the hidden input, so
all we have to do is lift it up to an argument:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt; is a pure function. It’s noteworthy that Python adopts
this second pattern by default. In python, all object methods take
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; as the first argument, except by convention they call it
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;Explicit is better than implicit&lt;/a&gt; indeed.&lt;/p&gt;

&lt;h3 id=&quot;mocking&quot;&gt;Mocking&lt;/h3&gt;

&lt;p&gt;Mocking frameworks usually do two things.&lt;/p&gt;

&lt;p&gt;The first is they help you set up value objects to act as inputs. The
harder your language makes it to set up complex values, the more
useful you’ll find this. But that’s an aside.&lt;/p&gt;

&lt;p&gt;The second is more interesting in this discussion - they help you set
up the right side-causes to the function under test, and track that
the right side-effects have occurred after the test.&lt;/p&gt;

&lt;p&gt;Seen through the lens of side-effects, mocks are a flag that your code
is impure, and in the functional programmer’s eye, proof that
something is wrong. Instead of downloading a library to help us check
the iceberg is intact, we should be sailing around it.&lt;/p&gt;

&lt;p&gt;A hardcore TDD/Java guy once asked me how you do mocking in
Clojure. The answer is, we usually don’t. We usually see it as a sign
we need to refactor our code.&lt;/p&gt;

&lt;h2 id=&quot;design-smells-or-the-scent-of-nothingness&quot;&gt;Design Smells (or The Scent Of Nothingness)&lt;/h2&gt;

&lt;p&gt;If there were an &lt;a href=&quot;https://en.wikipedia.org/wiki/I-Spy_(Michelin)&quot;&gt;I-Spy&lt;/a&gt; book of side-effects, the two easiest targets
to spot would be functions that take no arguments, and functions that
return no value.&lt;/p&gt;

&lt;h3 id=&quot;no-arguments-signal-side-causes&quot;&gt;No Arguments Signal Side-Causes&lt;/h3&gt;

&lt;p&gt;Whenever you see a function with no arguments, one of
two things are true: Either it always returns exactly the same value,
or it’s getting its inputs from elsewhere (ie. it has side-causes).&lt;/p&gt;

&lt;p&gt;For example, this function must always, always return the same
integer (or it has side-causes):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;no-return-value-signals-side-effects&quot;&gt;No Return Value Signals Side-Effects&lt;/h3&gt;

&lt;p&gt;And whenever you see a function with no return value, then either it
has side-effects, or there was no point calling it:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;According to that function signature, there is absolutely no reason to
call this function. It doesn’t give you anything. The only reason to
call it is for the magical side-effects it promises it will silently
cause.&lt;/p&gt;

&lt;h2 id=&quot;summary--conclusion-y-thing&quot;&gt;Summary / Conclusion-y Thing&lt;/h2&gt;

&lt;p&gt;A real, intuitive awareness of side-effects will change the way you
look at coding. It will change everything from how you look at
individual functions, right up to overall systems-architecture. It
will change the way you look at programming languages, tools and
techniques. It changes everything. Go kill a side-effect today…&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Yes, I’m conflating OO and Java. In the context of Scala I think it’s fair to equate the two. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;One of them! &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;PureScript takes this idea further, and is worth looking into. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’ve had some great Clojure design discussions where we’ve used Haskell signatures to explain ourselves, verify the consistency of the design, and to summarise our conclusions. Yes, Clojure discussions. Haskell’s notation has a value that extends far beyond the language. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;See &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man perlvar&lt;/code&gt; for the exact definition. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>What Is Functional Programming?</title>
		  <pubDate>Tue, 29 Dec 2015 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2015/12/what-is-functional-programming.html</link>
		  <guid>http://blog.jenkster.com/2015/12/what-is-functional-programming.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;This is my take on what functional programming really is, in a way that will make sense to a jobbing programmer just trying to Get Stuff Done.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I put it to you that every function you write has two sets of inputs
and two sets of outputs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two? Only one, surely?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No, two. Definitely two. Let’s take a look at the first pair with this
example:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// NOTE: The language doesn't matter, but I've picked one with&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// explicit input &amp;amp; output types, for emphasis.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the input you’re used to thinking about is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int x&lt;/code&gt;, and the
output you’re used to is also an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s the first set of inputs &amp;amp; outputs. The traditional set, if you
will.  Now let’s see an example of the &lt;em&gt;second&lt;/em&gt; set of inputs and
outputs:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;processNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;InboxQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;According to the syntax, this function takes no inputs and returns no
output, and yet it’s obviously depending on something, and it’s
obviously doing something. The fact is, it has a &lt;em&gt;hidden&lt;/em&gt; set of
inputs and outputs. The hidden input is the state of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt;
before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;popMessage()&lt;/code&gt; call, and the hidden outputs are whatever
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process&lt;/code&gt; causes, plus the state of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt; after we’re done.&lt;/p&gt;

&lt;p&gt;Make no mistake - the state of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt; is a genuine input of this
function. The behaviour of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;processNext&lt;/code&gt; cannot be known without
knowing that value. And it’s a genuine output too - the result of
calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;processNext&lt;/code&gt; cannot be fully understood without considering
the new state of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InboxQueue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the second piece of code has hidden inputs and outputs. It requires
things, and causes things, but you could never guess what just by
looking at the API.&lt;/p&gt;

&lt;p&gt;These hidden inputs and outputs have an official name:
“side-effects”. There are many kinds of side-effects, but they all
come together under the same concept: “when we call this function,
what does it need that isn’t in the argument list, and what does it do
that isn’t part of the return value?”&lt;/p&gt;

&lt;p&gt;(Actually I think we need two terms: “side-effects” for the hidden
outputs, and “side-causes” for the hidden inputs. For most of the rest
of this post I’ll use “side-effects” for brevity, but I’m definitely
talking about side-causes too. I’m talking about all &lt;em&gt;hidden&lt;/em&gt; inputs
and outputs.)&lt;/p&gt;

&lt;h2 id=&quot;side-effects-are-the-complexity-iceberg&quot;&gt;Side-Effects are the Complexity Iceberg&lt;/h2&gt;

&lt;p&gt;When functions have side-effects (and side-causes), you can look at a
function like this:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;processMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Channel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and think you’ve got an idea of what it’s doing, and be totally
wrong. There’s no way to know what it requires or what it will do
without looking inside. Does it take a message off the channel and
process it? Probably. Does it close your channel if some condition is
true? Maybe. Does it update a count in the database somewhere?
Perhaps.  Does it explode if it can’t find the logging directory path
it was expecting? It might.&lt;/p&gt;

&lt;p&gt;Side-effects are the complexity iceberg. You look at the function
signature, and the name, and think you’ve got a sense of what you’re
looking at. But hidden beneath the surface of the function signature
could be absolutely anything. Any hidden requirement, any hidden
change. Without looking at the implementation, you’ve no way of
knowing what’s really involved. Beneath the surface of the API is a
potentially vast block of extra complexity. To grasp it, you’ll only
have three options: dive down into the function definition, bring the
complexity to the surface, or ignore it and hope for the best. And in
the end, ignoring it is usually a titanic mistake.&lt;/p&gt;

&lt;h2 id=&quot;isnt-this-what-encapsulations-about&quot;&gt;Isn’t This What Encapsulation’s About?&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Encapsulation is about hiding implementation details. About hiding the
innards of the code so the caller doesn’t need to worry about
them. That remains a good principle, but it’s not what we’re talking
about.&lt;/p&gt;

&lt;p&gt;Side-effects aren’t about “hiding implementation details” - they’re
about hiding the code’s relationship with the outside world. A
function with side-causes has undocumented assumptions about what
&lt;em&gt;external&lt;/em&gt; factors it’s depending on. A function with side-effects has
undocumented assumptions about what &lt;em&gt;external&lt;/em&gt; factors it’s going to
change.&lt;/p&gt;

&lt;h2 id=&quot;are-side-effects-bad&quot;&gt;Are Side-Effects Bad?&lt;/h2&gt;

&lt;p&gt;When they work exactly as the original programmer expected, no,
they’re probably fine. But there’s the rub: we have to trust that the
the hidden expectations of the original programmer were correct, and
will remain correct as time marches on.&lt;/p&gt;

&lt;p&gt;Have we set up the state of the world the way this function expected
when it was written? Or did the world get changed somewhere? Perhaps
because a seemingly-unconnected piece of code changed. Or because
we’re installing the software in a new environment. Hidden assumptions
about the state of the world mean we have hidden hopes that it’s
similar enough to work.&lt;/p&gt;

&lt;p&gt;Can we test this code? Not in isolation. Unlike a circuit board, we
can’t just plug into its inputs and check its outputs. We have to
break open the code, figure out its &lt;em&gt;hidden&lt;/em&gt; causes and effects, and
simulate the world it’s supposed to exist in. I’ve seen several
TDD’ers spin in circles about whether they should do black box or
white box testing. The answer is, you ought to do black box testing -
you ought to be able to ignore the implementation details - but if you
allow side-effects, you can’t. Side-effects close the door to black
box testing, because you can’t get to the inputs &amp;amp; outputs without
cracking the box open and learning what’s inside.&lt;/p&gt;

&lt;p&gt;This effect is amplified for debugging. If a function doesn’t allow
side-effects (or side-causes), you can understand whether it’s correct
just by giving it some inputs and checking the outputs. But a function
with side-effects? There’s no upper-limit to how many other parts of
the system you’ll have to consider. When it’s allowed to depend on
anything, and cause anything, then the bugs could be anywhere.&lt;/p&gt;

&lt;h2 id=&quot;we-can-always-surface-side-effects&quot;&gt;We Can Always Surface Side-Effects&lt;/h2&gt;

&lt;p&gt;Can we do anything about this complexity? Yes. It’s actually pretty
simple to get started: If a function has something as an input, just
say so. If it returns something as an output, declare it. Simple as that.&lt;/p&gt;

&lt;p&gt;Let’s try an example. Here’s a function with a hidden input. Bonus
points if you spot it quickly:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getCurrentProgram&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TVGuide&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Schedule&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSchedule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;nc&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;programAt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function has a hidden input of the current time (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new
Date()&lt;/code&gt;). We can surface this complexity by just being honest about
this extra input:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getProgramAt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TVGuide&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Schedule&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSchedule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;nc&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;program&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;programAt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;program&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function now has no hidden inputs (or outputs).&lt;/p&gt;

&lt;p&gt;Let’s look at the pros and cons of this new version:&lt;/p&gt;

&lt;h3 id=&quot;cons&quot;&gt;Cons&lt;/h3&gt;

&lt;p&gt;It &lt;em&gt;looks&lt;/em&gt; more complex. It has three arguments instead of two.&lt;/p&gt;

&lt;h3 id=&quot;pros&quot;&gt;Pros&lt;/h3&gt;

&lt;p&gt;It isn’t more complex. Hiding a dependency didn’t make it simpler,
being honest about it doesn’t make it more complex.&lt;/p&gt;

&lt;p&gt;It’s vastly easier to test. Testing different times of day, clock
changes, leap years, will all be straightforward, because we can pass
in any time we like. I’ve seen code like the first version in
production, with all sorts of clever tricks to spoof the current
system clock for testing’s sake.  Imagine the effort, when we can just
make it a parameter!&lt;/p&gt;

&lt;p&gt;It’s easier to reason about: This function now just describes a
relationship between its inputs and its outputs. If you know the
inputs, you know what the result should be, and you know everything
about the result. &lt;em&gt;This is a big deal&lt;/em&gt;. We can verify this code in
isolation. As long as we’ve tested the relationship between inputs and
outputs, we’ve tested the whole of the function.&lt;/p&gt;

&lt;p&gt;(And as an aside, it’s also more useful. We get, “what program starts in
an hour?” code for free.)&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-pure-function&quot;&gt;What is a ‘Pure Function’?&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Drumroll please.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, finally, with an awareness of hidden inputs &amp;amp; outputs, we can
give, “a jobbing programmer’s definition of pure functions”:&lt;/p&gt;

&lt;p&gt;A function is called ‘pure’ if all its inputs are &lt;em&gt;declared&lt;/em&gt; as
inputs - none of them are hidden - and likewise all its outputs are
&lt;em&gt;declared&lt;/em&gt; as outputs.&lt;/p&gt;

&lt;p&gt;In contrast, if it has hidden inputs or outputs, it’s ‘impure’, and
the contract we think the function offers is only half the story. The
iceberg of complexity looms. We can never use impure code “in
isolation”. We can never test it in isolation. It always depends on
other things which we have to keep track of whenever we want to test
or debug.&lt;/p&gt;

&lt;h2 id=&quot;what-is-functional-programming&quot;&gt;What is ‘Functional Programming’?&lt;/h2&gt;

&lt;p&gt;With an awareness of pure and impure functions, we can now give,
“a jobbing programmer’s definition of functional programming”:&lt;/p&gt;

&lt;p&gt;Functional programming is about writing pure functions, about removing
hidden inputs and outputs as far as we can, so that as much of our
code as possible &lt;em&gt;just&lt;/em&gt; describes a relationship between inputs and
outputs.&lt;/p&gt;

&lt;p&gt;We accept that some side-effects are inevitable - most programs are
run for what they &lt;em&gt;do&lt;/em&gt; rather than what they return, but within our
program we will exercise tight control. We will eliminate side-effects
(and side-causes) wherever we can, and tightly control them whenever
we can’t.&lt;/p&gt;

&lt;p&gt;Or put another way: Let’s not hide what a piece of code needs, nor
what results it will yield.  If a piece of code needs something to run
correctly, let it say so. If it does something useful, let it declare
it as an output. When we do this, our code will be clearer. Complexity
will come to the surface, where we can break it down and deal with it.&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-functional-programming-language&quot;&gt;What is a ‘Functional Programming Language’?&lt;/h2&gt;

&lt;p&gt;Every language supports pure functions - it’s hard to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add(x, y)&lt;/code&gt;
impure&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. And in many cases converting an impure function to a
pure one is just a case of lifting &lt;em&gt;all&lt;/em&gt; its inputs and outputs into
the function signature, so that the signature totally describes its
behaviour. So are all programming languages ‘functional’?&lt;/p&gt;

&lt;p&gt;No. Because then the term would be meaningless.&lt;/p&gt;

&lt;p&gt;So what can we give as a “jobbing programmer’s definition of a
functional programming language”?&lt;/p&gt;

&lt;p&gt;A functional programming language is one that supports and encourages
programming without side-effects.&lt;/p&gt;

&lt;p&gt;Or more specifically: A functional language actively helps you
eliminate side-effects wherever possible, and tightly control them
wherever it’s not.&lt;/p&gt;

&lt;p&gt;Or more dramatically: A functional language is actively hostile to
side-effects. Side-effects are complexity and complexity is bugs and
bugs are the devil. A functional language will help you be hostile to
side-effects too. Together you will beat them into submission.&lt;/p&gt;

&lt;h2 id=&quot;is-that-it&quot;&gt;Is That It?&lt;/h2&gt;

&lt;p&gt;Yes. There are a couple of subtleties - things you probably never
thought of as a hidden input before, but that’s the essence. But start
building software with the perspective of “side-effects are the first
enemy” and it will change everything you know about programming. &lt;a href=&quot;/2015/12/which-programming-languages-are-functional.html&quot;&gt;Join me for part two&lt;/a&gt;, in which we take an awareness of side-effects, and
functional programming, and fire a scattergun over the programming
landscape.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;

&lt;p&gt;This post comes out of a couple of discussions about the nature of
functional programming. Particularly a chat with &lt;a href=&quot;https://twitter.com/sleepyfox&quot;&gt;Sleepyfox&lt;/a&gt; discussing
whether JavaScript could be considered a functional programming
language, with the right libraries. My answer was an instinctive no,
but thinking through /why/ lead me along a very fruitful chain of
thought.&lt;/p&gt;

&lt;p&gt;Hat tip to &lt;a href=&quot;https://twitter.com/jarohen&quot;&gt;James Henderson&lt;/a&gt;, which whom I have bounced around
many fruitful functional ideas this year.&lt;/p&gt;

&lt;p&gt;And thanks to &lt;a href=&quot;https://twitter.com/malcolmsparks&quot;&gt;Malcolm Sparks&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/llaisdy&quot;&gt;Ivan Uemlianin&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/jclermont&quot;&gt;Joel Clermont&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/katyemoe&quot;&gt;Katy Moe&lt;/a&gt;
and my homophonic-doppleganger &lt;a href=&quot;https://twitter.com/cdpjenkins&quot;&gt;Chris Jenkins&lt;/a&gt; for proofreading &amp;amp;
suggestions.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Although Java tries really hard. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Quote of the Week - Doug Crockford</title>
		  <pubDate>Fri, 30 Oct 2015 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2015/10/quote-of-the-week-doug-crockford.html</link>
		  <guid>http://blog.jenkster.com/2015/10/quote-of-the-week-doug-crockford.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;I’m now thinking I’ve got two completely different types of objects:
those containing only data, which are things I share with JSON; and
things containing only methods, which are things I can share with
applications.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PSGEjv3Tqo0&quot;&gt;Doug Crockford - The Better Parts&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think Doug Crockford’s great, but it does seem like he’s getting to
Functional Programming by the absolute slowest route possible.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Geocoding With Elm and ArcGIS, Part 3</title>
		  <pubDate>Wed, 07 Oct 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/10/geocoding-with-elm-and-arcgis-part-3.html</link>
		  <guid>http://blog.jenkster.com/2015/10/geocoding-with-elm-and-arcgis-part-3.html</guid>
		  <description>&lt;p&gt;After &lt;a href=&quot;http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-1.html&quot;&gt;part 1&lt;/a&gt; and
&lt;a href=&quot;http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-2.html&quot;&gt;part 2&lt;/a&gt;, I thought I was finished with this feature, but
&lt;a href=&quot;https://disqus.com/by/ariaroooefe/&quot;&gt;Ariarooo Efe&lt;/a&gt;
rightly &lt;a href=&quot;http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-1.html#comment-2293898738&quot;&gt;comments&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[in] the online demo of the app, if there are no results the user isn’t told anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This feedback is trivial to add, so let’s just see what quick work Elm
makes of it.&lt;/p&gt;

&lt;h2 id=&quot;the-model&quot;&gt;The Model&lt;/h2&gt;

&lt;p&gt;Recapping on the model of the app:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;places&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-1.html&quot;&gt;Part 1&lt;/a&gt; explains how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;places&lt;/code&gt; models the data we’re loading, and makes
a clear, type-checked distinction between these cases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We haven’t loaded any data yet.&lt;/li&gt;
  &lt;li&gt;We have loaded data, but that failed.&lt;/li&gt;
  &lt;li&gt;We’ve loaded data and it’s available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it also gives us, which in many frontend frameworks we might not
get, is a very clear distinction of, “we loaded some data and it was
empty”. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;places&lt;/code&gt; is an empty list, there’s no confusion - it
doesn’t mean “not asked” or “there was an error”, it only means there
are zero results.&lt;/p&gt;

&lt;p&gt;Armed with a correct data model, we’re going to find the rest easy…&lt;/p&gt;

&lt;h2 id=&quot;the-view&quot;&gt;The View&lt;/h2&gt;

&lt;p&gt;In the case of “no results”, the value of places will be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just (Ok
[])&lt;/code&gt;. That is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just ...&lt;/code&gt; - we’ve got some data.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok ...&lt;/code&gt; - we got it successfully.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; - it was the empty list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can update our rootView to add an extra case in:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;rootView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rootView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uiChannel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentLocation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;places&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Err&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;alert alert-danger&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;-- This is the new case:&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;alert alert-warning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;No results found.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resultsList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uiChannel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentLocation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(Note that we put the more specific match &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just (Ok [])&lt;/code&gt; before the
more general one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Just (Ok xs)&lt;/code&gt;, because patterns are checked in order
and the first one wins.)&lt;/p&gt;

&lt;h2 id=&quot;were-done&quot;&gt;We’re done.&lt;/h2&gt;

&lt;p&gt;Yup, there’s almost no work to do. Why? Because we had a good data
model to begin with - one that was clearly defined and correctly
represented the different states our app could be in.&lt;/p&gt;

&lt;p&gt;Say it long, say it loud, programming begins with data-modeling.&lt;/p&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;

&lt;p&gt;The whole app is a little larger, and I’ll be writing up other
pieces. In the meantime, you can see the geocoding part in action by
&lt;a href=&quot;http://krisajenkins.github.io/beeline-demo/&quot;&gt;playing with the finished hackday app here&lt;/a&gt; and then &lt;a href=&quot;https://github.com/krisajenkins/beeline-demo&quot;&gt;read the source code&lt;/a&gt; to learn more.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Timing Code in ClojureScript</title>
		  <pubDate>Fri, 25 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/timing-code-in-clojurescript.html</link>
		  <guid>http://blog.jenkster.com/2015/09/timing-code-in-clojurescript.html</guid>
		  <description>&lt;p&gt;Here’s a handy little ClojureScript macro that helps you time how long
code blocks take. It’s exactly like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(clojure.core/time)&lt;/code&gt;, in that it
takes a code block and tells you how long it took to execute, but
specially for ClojureScript it piggy-backs on the JavaScript &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt;
API, for pretty output in the inspector pane. You’d use it like this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;console-time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Rendering Big Thing&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;render-to-dom&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lots-of-data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the browser’s inspector console will print out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rendering Big
Thing: 10070.868ms&lt;/code&gt; when it’s done.&lt;/p&gt;

&lt;p&gt;How does it work? Well, it’s really just wrapping a code block in two
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt; API calls, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.time(&amp;lt;label&amp;gt;)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.timeEnd(&amp;lt;label&amp;gt;)&lt;/code&gt;. We could almost say:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;console-time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.timeEnd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…splicing the body between those calls. But that would have a flaw:
instead of returning the body’s result value, we’re returning the
result of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.timeEnd&lt;/code&gt;, which is always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we take a second pass:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;console-time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.timeEnd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s pretty obvious that’s wrong too - right return value, but it’s
executing the body twice. That’s bad for performance, and outright
broken if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; contains side-effects&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;There’s nothing for it - we’re going to have to run the block once,
capture its return value, and return that captured result later.&lt;/p&gt;

&lt;p&gt;To capture it, we’ll have to create a temporary local var, with a
guaranteed-unique name. We can do that by appending a hash symbol, as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result#&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that, the final code should make sense:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;console-time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.timeEnd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js/console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember if you’re using this forreals, all ClojureScript macros must
go in a Clojure file, and be imported with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(refer-macros ...)&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Don’t worry, I know &lt;em&gt;you&lt;/em&gt; would never write code with side-effects. We’re worrying about &lt;em&gt;them&lt;/em&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Things I Love About Languages I Hate</title>
		  <pubDate>Fri, 25 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/things-i-love-about-languages-i-hate.html</link>
		  <guid>http://blog.jenkster.com/2015/09/things-i-love-about-languages-i-hate.html</guid>
		  <description>&lt;p&gt;I’m worried I’ve seemed a bit grumpy about tech lately. So, in an
attempt to find silver linings and stream some positivity from my
corner of the technosphere&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, here are some things I love about
the things I hate:&lt;/p&gt;

&lt;h2 id=&quot;php&quot;&gt;PHP&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;It has all the best content-management systems. God only knows why, but it does.&lt;/li&gt;
  &lt;li&gt;It gets fast results for beginners, and you can’t underestimate the value of that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;bash&quot;&gt;Bash&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;If you just typed it at the command line, you’re 80% of the way to automating it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;javascript&quot;&gt;JavaScript&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;It’s the only programming language my mother has installed. And my
grandmother. And, basically, everyone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;plsql-and-variants&quot;&gt;PL/SQL (and variants)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;It has, hands down, the best SQL integration of any language. That’s
the only thing it’s got, but it’s got that. If your job just involves
manipulating database rows, it’ll be written before your package
manager has finished downloading an internet’s worth of ORM
dependencies.  And if your program processes a million database
rows, a PL/SQL can finish the job before your ORM has finished
deserialising the first 10,000.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;scala&quot;&gt;Scala&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Along with a few other, better languages, it’s a bit of a magnet for smart people right now.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;mean&quot;&gt;MEAN&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Mongo, Express, Angular &amp;amp; Node. It’s a really good acronym. I mean,
really good. It’s memorable and sounds cool &amp;amp; edgy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;How can you have a corner of a sphere? &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Geocoding With Elm and ArcGIS, Part 2</title>
		  <pubDate>Fri, 25 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-2.html</link>
		  <guid>http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-2.html</guid>
		  <description>&lt;p&gt;Following on from &lt;a href=&quot;/2015/09/geocoding-with-elm-and-arcgis-part-1.html&quot;&gt;part 1&lt;/a&gt;, we had completed our description of the app,
and the event handlers, and we just needed to worry about making an
AJAX request, decoding the response, and rendering the HTML.&lt;/p&gt;

&lt;p&gt;Just. :-)&lt;/p&gt;

&lt;h2 id=&quot;ajax&quot;&gt;AJAX&lt;/h2&gt;

&lt;p&gt;ArcGIS has a nice API for geocoding&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. We send a GET with the term
as a query parameter, we get back some JSON for places in the world
that match that search term. It’s easy to use.&lt;/p&gt;

&lt;p&gt;For our wiring, we have a search term, and we want to generate the
side-effect that eventually returns a list of places. Remembering that
that side-effect may fail with an HTTP error, we get this type
signature:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;findPlaces&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To read the actual implementation you’ll need to know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&amp;gt;&lt;/code&gt; is an
operator that basically reads as a unix pipe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; &lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;- take the results of
the last function and pass them in as the input to the next function:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;findPlaces&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;http://geocode.arcgis.com/arcgis/rest/services&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/World/GeocodeServer&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/findAddressCandidates?f=json&amp;amp;singleLine=&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uriEncode&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decodePlaces&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toResult&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s a lot of type-wrangling in there, but the noteworthy bit is
that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Http.get&lt;/code&gt; takes a JSON-decoder as its first argument, which will
fire if the get request was successful.&lt;/p&gt;

&lt;h2 id=&quot;json&quot;&gt;JSON&lt;/h2&gt;

&lt;p&gt;Let’s look at &lt;a href=&quot;http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?f=json&amp;amp;singleLine=royal+festival+hall&quot;&gt;a sample response from the API&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;spatialReference&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;wkid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4326&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;latestWkid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4326&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;candidates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Royal Festival Hall&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;-0.11599726799954624&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;51.50532882800047&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;score&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;attributes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;extent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;xmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;-0.120998&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ymin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;51.500329&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;xmax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;-0.110998&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ymax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;51.510329&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For JSON-decoding I always pull in &lt;a href=&quot;https://twitter.com/circuithub][CircuitHub]]'s [[http://package.elm-lang.org/packages/circuithub/elm-json-extra/latest/&quot;&gt;JSON extras&lt;/a&gt;, so let’s
import those:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Decode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Json&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Extra&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exposing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the parsing is reduced to two functions, which make use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:=&lt;/code&gt; to
access a property and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;at&lt;/code&gt; to walk a nested path down the tree.&lt;/p&gt;

&lt;h3 id=&quot;decode-one-place&quot;&gt;Decode one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Place&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;decodePlace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Decoder&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;decodePlace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;address&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;location&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;location&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;decode-the-list-of-places&quot;&gt;Decode the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Places&lt;/code&gt;&lt;/h2&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;decodePlaces&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Decoder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;decodePlaces&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;candidates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decodePlace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the actual hackday I wrote this code, I found this kind of thing
very fast to write. You’d think having to write a parser for JSON
before you can use it would slow you down, but certainly on that day I
found it sped things up: The first pass was slower, sure, but as I
built out the app and discovered that my initial assumptions about the
schema were wrong, having the compiler tell me all the places my
assumptions were wrong saved a lot of time.&lt;/p&gt;

&lt;h2 id=&quot;right-thats-it-were-done&quot;&gt;Right, That’s It, We’re Done&lt;/h2&gt;

&lt;p&gt;Oh wait, no. We haven’t actually displayed anything to the user yet.&lt;/p&gt;

&lt;h2 id=&quot;rendering&quot;&gt;Rendering&lt;/h2&gt;

&lt;p&gt;So the last piece we need is a rendering function. HTML gets huge, so
I’ll just focus on an illustrative piece and &lt;a href=&quot;https://github.com/krisajenkins/beeline-demo/blob/master/src/FindAddress/View.elm&quot;&gt;point you to the source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most HTML-rendering functions in Elm have essentially the same
signature. You might expect it to be as simple as:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;searchForm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…but it’s &lt;em&gt;slightly&lt;/em&gt; more complicated than that, because DOM.&lt;/p&gt;

&lt;p&gt;It’s not enough to just generate HTML. We also need a way for user
clicks and keypresses to generate events (as Elm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Actions&lt;/code&gt;). So the
most common type signature is some variant of:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;searchForm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address Action&lt;/code&gt; will give us a way to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onClick&lt;/code&gt; events
generate a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt;, without polluting our rendering code with
business logic. It’s a channel, queue, or postbox where we can send
event data&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;So, let’s look at our search box. &lt;a href=&quot;/2015/09/responsive-youtube-videos-with-elm.html&quot;&gt;(Here’s a primer for reading Elm’s HTML syntax.)&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;searchForm&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;form-group&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;form-control&quot;&lt;/span&gt;
             &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autofocus&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;
             &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;keyup&quot;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;targetValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TermChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;btn btn-lg btn-block btn-success&quot;&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;submit&quot;&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Search&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s look at a few of those pieces:&lt;/p&gt;

&lt;h3 id=&quot;onclick&quot;&gt;onClick&lt;/h3&gt;

&lt;p&gt;This makes a button click turn into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Submit&lt;/code&gt; action:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Submit&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;disabled&quot;&gt;disabled&lt;/h3&gt;

&lt;p&gt;Here we disable the button when there’s a load in-flight. It’s an easy
way to give the user some feedback that the click actually caused something:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…recall that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;model.loading&lt;/code&gt; is handled in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt;
function. The button is not made responsible for tracking which AJAX
requests are in-flight, as that would be an insane abuse of the single
responsibility principal. It’s just a button that displays how it’s told.&lt;/p&gt;

&lt;h3 id=&quot;autofocus&quot;&gt;autofocus&lt;/h3&gt;

&lt;p&gt;For another UX nicety, it’s trivial to make this form field capture the
cursor when the page renders:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;autofocus&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;on&quot;&gt;on&lt;/h3&gt;

&lt;p&gt;The only really juicy part of this code is the input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyup&lt;/code&gt; event
handler. It’s a little more complex because it needs to refer to
the value of the event target. It’s also interesting because it shows
how you can handle any arbitrary event type:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;keyup&quot;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;targetValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TermChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whenever there’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyup&lt;/code&gt; event, grab the element’s value, wrap it up
as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TermChange&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt;, and send it on its merry way.&lt;/p&gt;

&lt;h2 id=&quot;were-done&quot;&gt;We’re done&lt;/h2&gt;

&lt;p&gt;That’s it. A complete overview of a Geocoding module for an app
written in Elm. It feels like we covered a lot of pieces:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Describing data&lt;/li&gt;
  &lt;li&gt;Describing events&lt;/li&gt;
  &lt;li&gt;Handling events&lt;/li&gt;
  &lt;li&gt;AJAX-y side-effects&lt;/li&gt;
  &lt;li&gt;Decoding JSON&lt;/li&gt;
  &lt;li&gt;React-style rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that is a lot of pieces, but any app would need all of them
somewhere.  The nice thing about this approach is that each piece is
discrete - you can think about it and write it in isolation, and then
glue them together later&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. You can also easily split the writing
of them, so that coders who are good with HTML can focus on the
rendering. I am muchly fond of this approach in general, and Elm’s
implementation of it specifically. Especially when it’s a hack day and
I need to move fast &lt;em&gt;without&lt;/em&gt; breaking things.&lt;/p&gt;

&lt;h2 id=&quot;fin&quot;&gt;Fin&lt;/h2&gt;

&lt;p&gt;The whole app is a little larger, and I’ll be writing up other
pieces. In the meantime, you can see the geocoding part in action by
&lt;a href=&quot;http://krisajenkins.github.io/beeline-demo/&quot;&gt;playing with the finished hackday app here&lt;/a&gt; and then &lt;a href=&quot;https://github.com/krisajenkins/beeline-demo&quot;&gt;read the source code&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And they’re not paying me to say that. Well, actually, this app won a prize at the hackday, and ArcGIS were the sponsors, so maybe that does count as payment. :-D &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Thank you &lt;a href=&quot;https://twitter.com/rtfeldman&quot;&gt;Richard Feldman&lt;/a&gt; for that analogy. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Clojurians might find it interesting that this is very much like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.async&lt;/code&gt; channel, except it’s one-way. You can only write to an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt;, and it has a counterpart on the other side that can only be read from. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;It’s an approach that can work in many languages, but Elm makes the distinctions really clear. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Geocoding With Elm and ArcGIS, Part 1</title>
		  <pubDate>Fri, 25 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-1.html</link>
		  <guid>http://blog.jenkster.com/2015/09/geocoding-with-elm-and-arcgis-part-1.html</guid>
		  <description>&lt;p&gt;I recently &lt;a href=&quot;http://devpost.com/software/beeline-demo/&quot;&gt;wrote a navigation app for a hack day&lt;/a&gt;, and since it’s
written in Elm, and there aren’t enough blog posts about Elm, I
thought I’d break down some of the pieces. Here’s a nice juicy one:
letting the user search for a location, and turning that into latitude
&amp;amp; longitude - ‘geocoding’.&lt;/p&gt;

&lt;h1 id=&quot;the-spec&quot;&gt;The Spec&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;We need an input box you can type your search into.&lt;/li&gt;
  &lt;li&gt;When you submit, we fetch a list of possible matches from &lt;a href=&quot;https://www.arcgis.com/features/&quot;&gt;ArcGIS&lt;/a&gt;
(the company that sponsored the hack day in question, and who have a
Geocoding API).&lt;/li&gt;
  &lt;li&gt;We need to display those matches.&lt;/li&gt;
  &lt;li&gt;You can choose one. (A choice which will cause something else to happen. Something that’s outside the scope of this post).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see how Elm tackles it…&lt;/p&gt;

&lt;h1 id=&quot;the-implementation&quot;&gt;The Implementation&lt;/h1&gt;

&lt;p&gt;Every Elm app breaks down into a few simple parts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A data structure representing the state of the world.&lt;/li&gt;
  &lt;li&gt;A set of possible events that can occur.&lt;/li&gt;
  &lt;li&gt;An event handler: a function that takes the current state of the world, and one event,
and returns the new state of the world, plus any side-effects that
must occur.&lt;/li&gt;
  &lt;li&gt;A function that can display the current state of the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s break those pieces down:&lt;/p&gt;

&lt;h2 id=&quot;model&quot;&gt;Model&lt;/h2&gt;

&lt;p&gt;Our state of the world, our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt;, will need to capture the contents
of the form, the list of matching places, and the chosen
place. And for UX-sweetness we’ll add in a loading-flag, so we can
disable the form while we’re fetching results.&lt;/p&gt;

&lt;p&gt;In Elm-land we’ll model this as a record. First we’ll need to define
the type of a search result, which I’ll call a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Place&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;latitude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;longitude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can define the whole app state:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;searchTerm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;places&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chosenPlace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chosenPlace&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Place&lt;/code&gt;, of course, but initially no-one’s chosen
anything, so we’ll wrap it in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;places&lt;/code&gt; is the trickiest type to read here. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe (Result
Error (List Place))&lt;/code&gt; is saying:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt; We may or may not have…&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result Error ...&lt;/code&gt; the result of a request, which may be failure, or may
be…&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List Place&lt;/code&gt; a list of places.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. That’s the state of the world, the whole state of the
world, and will fully describe the state of the world for the lifetime
of the app&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;action&quot;&gt;Action&lt;/h2&gt;

&lt;p&gt;By convention, Elm describes all events that could occur in the system
with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt; type. What are the events that can occur in our app?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The user types something, changing our search term.&lt;/li&gt;
  &lt;li&gt;The user hits submit.&lt;/li&gt;
  &lt;li&gt;The internets give us a list of places.&lt;/li&gt;
  &lt;li&gt;The user chooses a place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That translates into a union type of:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Action&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ChangeTerm&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Submit&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PlacesResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ChoosePlace&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Place&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For those unfamiliar with the syntax, this is saying that an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt;
can be any one, and &lt;em&gt;only one&lt;/em&gt; of the values that follow. Some, like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChangeTerm&lt;/code&gt; carry a payload value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, some like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Submit&lt;/code&gt; are
just markers.&lt;/p&gt;

&lt;p&gt;That’s it. Those are the events, all the events, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt; fully
describes every event that can occur for the lifetime of the
app&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;update&quot;&gt;update&lt;/h2&gt;

&lt;p&gt;The next piece we need is an event handler, which we call
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt;. Let’s start with an easy, but incomplete version:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;ChangeTerm&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is saying, “if you give me an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt; and the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt; of
the world, I can process that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt; and give you the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt;,
plus any side-effects that need to occur (like kicking off an AJAX
request).”&lt;/p&gt;

&lt;p&gt;In this case, we’re just handling the “user types into the input box”
case, to get used to the syntax. We unpack the string that the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChangeTerm&lt;/code&gt; action holds, and update the model with it. This case
causes no side-effects, so we say that explicity with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Effects.none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The other easy event is “user chooses a place”. Let’s add that into our
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; function’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt; statement:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;ChoosePlace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chosenPlace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next up is submit:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Submit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PlacesResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;findPlaces&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s more interesting. We’re kicking off a search. In the model, we
set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loading&lt;/code&gt; flag. This is purely for UX. Alongside that, for the
first time, we have an interesting side-effect. We’re calling
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findPlaces&lt;/code&gt; to create a request, and then using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; to wrap the
response in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PlacesResponse&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt;, so that we’ll know know what
kind event it is when we come to process it later.&lt;/p&gt;

&lt;p&gt;We’ll see how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findPlaces&lt;/code&gt; is defined later. For now, let’s finish off
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; by defining how to handle the response:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;PlacesResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;places&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
                                 &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                         &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Effects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When we get a response, switch that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loading&lt;/code&gt; flag off, and store the
places.&lt;/p&gt;

&lt;p&gt;That’s it. That’s the business logic, all the business-logic, and fully describes
how every event changes the state of the world for the lifetime of the app&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;pause&quot;&gt;Pause&lt;/h2&gt;

&lt;p&gt;This seems like a lot, so let’s take a breather. We have events. We
have a state of the world. We have a function that moves the state of
the world forward.&lt;/p&gt;

&lt;p&gt;It’s nice that the events follow pretty directly from asking, “What can the user do?”&lt;/p&gt;

&lt;p&gt;It’s also nice that once we’ve describe how to handle each event,
we’re done with business logic.&lt;/p&gt;

&lt;p&gt;In the next release of Elm, the compiler will be able to warn you if
you miss out any event handlers&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, and that will be very nice indeed.&lt;/p&gt;

&lt;p&gt;So now we just needed to describe that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findPlaces&lt;/code&gt; function, and
worry about the UI. To do that we’ll need to talk about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Effects&lt;/code&gt;,
JSON-parsing and HTML-rending.&lt;/p&gt;

&lt;p&gt;Why don’t you go and make a cup of tea&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and &lt;a href=&quot;/2015/09/geocoding-with-elm-and-arcgis-part-2.html&quot;&gt;join me for part two&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the meantime, you can &lt;a href=&quot;http://krisajenkins.github.io/beeline-demo/&quot;&gt;play with the finished hackday app here&lt;/a&gt; and
&lt;a href=&quot;https://github.com/krisajenkins/beeline-demo&quot;&gt;read the source code&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Good luck trying to say something that definitive in an Angular app. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Good luck trying to say something that definitive in an Angular app. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Good luck trying to say…oh, you get the point. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And quickly, at that. Elm’s compiler is impressively fast. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Make it /properly/ mind. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Dude, Do You Even Fizzbuzz?</title>
		  <pubDate>Sat, 12 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/dude-do-you-even-fizzbuzz.html</link>
		  <guid>http://blog.jenkster.com/2015/09/dude-do-you-even-fizzbuzz.html</guid>
		  <description>&lt;p&gt;Ah, fizzbuzz, that venerable challenge of our industry. I’ve lost
count of the number of times I’ve been asked to fizzbuzz in an
interview. Seriously, I’d like to get a blindfold with “fizzbuzz”
embroidered on it, so if I’m sent to the whiteboard I can cover my
eyes and see if I’m yet able to Pin the Tail on the Fizzbuzz Donkey.&lt;/p&gt;

&lt;p&gt;Some people dislike it. Some refuse to do it at interview. Not
me. I’ve been on both sides of the interview table, and I’ve seen
glistening CVs turn into candidates that can barely find the right
side of the keyboard. So I’m fine with starting an interview with an
idiot filter. We’ll soon be on to talking about something more
interesting.&lt;/p&gt;

&lt;p&gt;But why am I writing about fizzbuzz? More importantly, why am I on
holidaycation, sitting at a free bar, and writing about fizzbuzz?
Because Someone Is Wrong On The Internet.&lt;/p&gt;

&lt;p&gt;I saw a blog post today on the “right way” to TDD fizzbuzz in an
interview, and it’s got my goat.&lt;/p&gt;

&lt;p&gt;I have mixed feelings about the value of TDD. I won’t get into the
gory details, because that’s worth an essay in itself, but the
particular aspect on my mind is that TDD has a tendency to lead you
into &lt;em&gt;spec blindness&lt;/em&gt;. That condition that every junior developer has
to learn about, where you think that correctly fulfilling the spec
leads to correct code (and a pat on the head). It does not. You
graduate from junior developer when you start seeing the need behind
the presenting problem&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. And with fizzbuzz, the spec is
deeply misleading.&lt;/p&gt;

&lt;p&gt;The spec goes something like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Given an integer n, print the integers from 0 to n.&lt;/li&gt;
  &lt;li&gt;Every time you reach a number wholly divisible by 3, print ‘fizz’ instead.&lt;/li&gt;
  &lt;li&gt;Every time you reach a number wholly divisible by 5, print ‘buzz’ instead.&lt;/li&gt;
  &lt;li&gt;Every time you reach a number wholly divisible by 3 &lt;em&gt;and&lt;/em&gt; 5, print ‘fizzbuzz’ instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, Mr Wrong On The Internet advocates starting with this test case:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fizz&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fizzbuzz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Yes, this hits the spec. But it’s testing too many things, and has
tests of trivia mixed in with testing useful code. But the big problem
is, if you start with “test the spec” as your guide then it’s
encouraging you to write the wrong code. It’s the programming
equivalent of treating the symptoms instead of going for the root
cause.&lt;/p&gt;

&lt;p&gt;Instead of string-munging through the symptoms, let’s step back and do
some quick analysis&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; on this problem. Fizzbuzz has few parts, and
almost all of them are crashingly dull:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Print stuff as a string&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yawn.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Generate a sequence from 0 to n.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yawn. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(range n)&lt;/code&gt;, or your language’s equivalent. Next.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Apply a transformation to a sequence.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dull programming, but it does open the opportunity to pontificate
about functional programming. I could probably even get the word
‘Functor’ in there, and that always gets the day moving. Still, dull
programming.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conditionally transform an integer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s the nugget. This is the /only/ interesting part of the
challenge. Fizzbuzz can be written as:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is the /only/ thing doing anything novel. Any coding you
do outside of defining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is merely gluing the algorithm into the
core libraries. And so I put it to you, any testing you do outside of
testing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is an integration test, and a crashingly dull one at
that. You might as well include writing tests for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.toString()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So if you ever ask me to write fizzbuzz in an interview, I’ll start by
writing a function of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int -&amp;gt; String&lt;/code&gt;. Actually I’ll probably do
it in Clojure, because I think it comes out neatest:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fizzbuzz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fizzbuzz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fizz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:buzz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or maybe I’ll go typecrazy with Haskell:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Fizzbuzz&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Fizz&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Buzz&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FizzBuzz&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fizzbuzz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Fizzbuzz&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fizzbuzz&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FizzBuzz&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Fizz&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Buzz&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s sweet. It changes the type and still keeps the untransformed
integers available.&lt;/p&gt;

&lt;p&gt;Someone will say I’m doing TDD wrong. So be it. I’m a heretic. I’m
saying if TDD is, “translating the spec-as-given into a test and then
writing passing code,” then TDD is wrong&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. However I solve fizzbuzz,
you won’t see me start with string-slicing tests&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And you graduate to senior developer when you learn to stop always trying to see the bigger picture, and remember that you’ve also just gotta ship. Balancing the bigger picture with the smaller one never ends. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Henderson’s Law states that all problems can be solved with one of two approaches: 1) Think, and 2) For chrissakes, THINK! &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Someone will say that that isn’t TDD either. Bravo! Please continue to say it. Please say it louder, so as to drown out the mainline rhetoric. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Besides, for fizzbuzz you want property-based testing, not example-based. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Responsive YouTube Videos With Elm</title>
		  <pubDate>Sun, 06 Sep 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/09/responsive-youtube-videos-with-elm.html</link>
		  <guid>http://blog.jenkster.com/2015/09/responsive-youtube-videos-with-elm.html</guid>
		  <description>&lt;p&gt;I recently &lt;a href=&quot;http://devpost.com/software/beeline-demo/&quot;&gt;wrote an navigation app for a hack day&lt;/a&gt;, and since it’s
written in Elm, and there aren’t enough blog posts about Elm, I
thought I’d break down some of the pieces. Let’s warm up with a
simple, but exceptionally useful one: Embedding a responsive video.&lt;/p&gt;

&lt;p&gt;This is so easy it’s almost cheating. Most of the hard work is
offloaded to &lt;a href=&quot;http://getbootstrap.com/components/#media&quot;&gt;Bootstrap 3&lt;/a&gt;. But since it’s so useful it’s worth spelling
out. All we need is a function that takes a YouTube URL, and returns
some HTML. That translates to this type signature:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;youtube&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we need to know how to generate HTML in Elm. It’s pretty
easy. Almost every HTML function takes a list of attributes, followed
by a list of children. So a Bootstrap alert messsage might be:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;alert alert-danger&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Ohnoes!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…or with a title:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;alert alert-danger&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Error!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Ohnoes!&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(You can see there in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h1&lt;/code&gt; tag that you &lt;em&gt;must&lt;/em&gt; specify the list of
attributes, even if it’s empty.)&lt;/p&gt;

&lt;p&gt;With that, the code for our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;youtube&lt;/code&gt; function is an easy
translation of the Bootstrap docs:&lt;/p&gt;

&lt;div class=&quot;language-elm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;youtube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;embed-responsive embed-responsive-16by9&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iframe&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;embed-responsive-item&quot;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s all there is to it.&lt;/p&gt;

&lt;p&gt;(For the curious, &lt;a href=&quot;http://package.elm-lang.org/packages/krisajenkins/elm-exts/8.4.0/Exts-Html-Bootstrap#video&quot;&gt;I’ve published a slightly fancier version&lt;/a&gt; as a library.)&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>When Should You Bother With A Reader Monad?</title>
		  <pubDate>Thu, 06 Aug 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/08/when-should-you-bother-with-a-reader-monad.html</link>
		  <guid>http://blog.jenkster.com/2015/08/when-should-you-bother-with-a-reader-monad.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;I have been thinking about Reader monads, and the bothering-with
thereof. Here’s this morning’s stream of consciousness…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thought of the day - what’s the difference between using a function
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo :: Config -&amp;gt; SomeResult&lt;/code&gt; and using the monad &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo :: Reader Config SomeResult&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Answer: Technically none. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data Reader r a = Reader { runReader :: r -&amp;gt; a }&lt;/code&gt;
is really an equation saying they’re exactly equivalent: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader r a&lt;/code&gt; equals &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r -&amp;gt; a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So what’s the point of the Reader monad? Why (or rather, when) should
you bother with a Reader monad instead of a straight argument?&lt;/p&gt;

&lt;p&gt;Answer: composition. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt; version composes
(maps/sequences/etc.) trivially, to produce a single function that’s
just waiting for its config. The vanilla version requires more
plumbing (&amp;amp; thought) to compose.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Partly that’s offset in Clojure - we don’t just use functional
composition, we can use syntactic composition too (because macros).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But that’s my conclusion of a night in the hammock. The Reader monad
is a transformational trick to enable easier functional
composition. And so, the “should I use it?” question follows as, “am I
doing a lot of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config&lt;/code&gt; plumbing to sequence these function calls?”&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Extending Esqueleto for Type-Safe Postgresql Queries</title>
		  <pubDate>Tue, 28 Jul 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/07/extending-esqueleto-for-type-safe-postgresql-queries.html</link>
		  <guid>http://blog.jenkster.com/2015/07/extending-esqueleto-for-type-safe-postgresql-queries.html</guid>
		  <description>&lt;p&gt;It’s no great secret that &lt;a href=&quot;https://github.com/krisajenkins/yesql&quot;&gt;I’m not a huge fan of SQL DSLs&lt;/a&gt;. They tend to
be great for the simple stuff, but they break down very quickly
as soon as you try to do anything non-trivial. So it’s a bit odd
that I find myself picking up a Haskell one - &lt;a href=&quot;https://hackage.haskell.org/package/esqueleto&quot;&gt;Esqueleto&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why am I risking heartbreak? Well, because as long as I can stay
on the Persistent/Esqueleto path, I’ll get DB migrations for free,
and compile-time integrity checks that can cover my database,
webserver and frontend in one pass.&lt;/p&gt;

&lt;p&gt;That kind of compile-time checking - for almost-free - is not to be
sniffed at. If I change a datastructure, I know that the all the
server code, all the UI code and the complete database schema are in
sync. I don’t think I’ve ever worked on a project that’s achieved that
dream, so it’s worth a little perseverance.&lt;/p&gt;

&lt;p&gt;As predicted, Esqueleto broke down for me pretty quickly. But it got
back up off the floor quickly too, and that’s the point of this post:
Let’s see how we can get a typesafe database query that uses SQL
features the library authors didn’t consider…&lt;/p&gt;

&lt;p&gt;My use-case, I confess, is weird. But that’s sort of the point - this
is stuff the authors wouldn’t have foreseen. I am importing some data
from a shoddy source, and then cleaning it up later. So I already had
this SQL statement:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For some reason &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$DATA_SUPPLIER&lt;/code&gt; is sticking weird characters around
the description, and we didn’t catch it on import. We want to update
any products that have the magic character &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chr(160)&lt;/code&gt; stuck on them.&lt;/p&gt;

&lt;p&gt;Let’s see that update statement naively ported to Esqueleto:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;tidyDescriptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlPersistM&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tidyDescriptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ProductDescription&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trimDescription&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                   &lt;span class=&quot;n&quot;&gt;where_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^.&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProductDescription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trimDescription&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trimDescription&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^.&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProductDescription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The syntax is a little funky, but even if you don’t really read
Haskell you can probably see how it’s trying to say the same thing as
the SQL above.&lt;/p&gt;

&lt;p&gt;Unfortunately, Esqueleto has already broken down on us: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trim&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chr&lt;/code&gt; are apparently too Postgres-specific, and aren’t supported.&lt;/p&gt;

&lt;p&gt;So what shall we do? Break out a horrible, string-guzzling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rawSql&lt;/code&gt;
function, losing type safety and opening up SQL Injection vectors? No!
We just teach Esqueleto about these functions. First &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chr&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;chr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;IsString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlExpr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlExpr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unsafeSqlFunction&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;chr&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code basically reads as, “There’s a function called =chr= that
takes an integer and returns a string, both in a SQL-ish context. Trust
me. There really is.”&lt;/p&gt;

&lt;p&gt;And then:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;IsString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlExpr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlExpr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SqlExpr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;unsafeSqlFunction&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;trim&quot;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unsafeSqlBinOp&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FROM&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which reads as, “There’s a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trim&lt;/code&gt; that
takes two strings and has weird syntax, but if you call it this way
you’ll get a string back. Honest.”&lt;/p&gt;

&lt;p&gt;With that, our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; statement works. We don’t get type-safety
&lt;em&gt;within&lt;/em&gt; these functions - Haskell is just blindly taking our promise
that these types are correct - but I can live with that. This is code
we’ll write once and never change. The important thing is that every
&lt;em&gt;use&lt;/em&gt; of these new functions get the guarantees we’re looking for, and
they were pretty trivial to add.&lt;/p&gt;

&lt;p&gt;So an SQL DSL that doesn’t abandon you to DSHell. Cautiously, I
&lt;em&gt;think&lt;/em&gt; I could make friends here…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Map, Reduce and the Fold-Twins</title>
		  <pubDate>Tue, 07 Jul 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/07/map-reduce-and-the-fold-twins.html</link>
		  <guid>http://blog.jenkster.com/2015/07/map-reduce-and-the-fold-twins.html</guid>
		  <description>&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; &lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; are the bread &amp;amp; butter tools of functional
programming, but if you’re new to FP it’s easy to get muddled about
which to use when, so here’s my mental checklist:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you have a sequence and you want a sequence, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If you have a sequence and you want a single value, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; (or&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fold&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;If you have a single value and you want a sequence, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unfold&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s a simplification, but a good rule of thumb to get started
with. (The twist comes when you realise that the “single value” that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; produces can itself be a new sequence.) But hopefully that
will serve as a simple signpost if you’re coming from a world of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt;
loops and wondering how to break things down.&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fold&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldr&lt;/code&gt; , depending on your language. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>This Week In The Browser</title>
		  <pubDate>Wed, 01 Jul 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/07/this-week-in-the-browser.html</link>
		  <guid>http://blog.jenkster.com/2015/07/this-week-in-the-browser.html</guid>
		  <description>&lt;p&gt;ClojureScript has &lt;a href=&quot;https://asciinema.org/a/22767&quot;&gt;opened a window to no-JVM&lt;/a&gt;…&lt;/p&gt;

&lt;p&gt;Elm has &lt;a href=&quot;http://elm-lang.org/blog/compiler-errors-for-humans&quot;&gt;released a big improvement in its compiler errors&lt;/a&gt;…&lt;/p&gt;

&lt;p&gt;PureScript has &lt;a href=&quot;https://github.com/purescript/purescript/releases/tag/v0.7.0&quot;&gt;released an order of magnitude performance boost&lt;/a&gt; in its compiler times…&lt;/p&gt;

&lt;p&gt;And there is genuine hope of &lt;a href=&quot;https://github.com/commercialhaskell/stack/issues/337&quot;&gt;progress for practical GHCJS&lt;/a&gt;…&lt;/p&gt;

&lt;p&gt;I’m calling this a good week for the browser.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>JavaScript - The Collection of Parts</title>
		  <pubDate>Wed, 17 Jun 2015 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2015/06/javascript-the-collection-of-parts.html</link>
		  <guid>http://blog.jenkster.com/2015/06/javascript-the-collection-of-parts.html</guid>
		  <description>&lt;p&gt;JavaScript is awful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s got Good Parts!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes, but it’s also got Bad Parts. Lots of them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We won’t use those parts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll be disciplined.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Seriously, how?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll be really disciplined.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hmm. What about the pitfalls you don’t all know about?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Okay, we’ll use a linter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That would shield you from the Worst Parts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use ES2015.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That would shield you from the Next-to-Worst Parts.&lt;/p&gt;

&lt;p&gt;What about the poor async support?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use Promises.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What about the broken data-modeling?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use ImmutableJS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What about the broken data-processing?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use Underscore.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What about the broken data-flow?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use RxJS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What about the broken data-consistency?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use TypeScript.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What about the broken rendering?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll use React.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Why don’t you just start with a well-designed language?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Oh we couldn’t do that - there’d be too much to learn!&lt;/em&gt;&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>A Brief And Partial Review Of Haskell In The Browser</title>
		  <pubDate>Tue, 03 Feb 2015 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2015/02/a-brief-and-partial-review-of-haskell-in-the-browser.html</link>
		  <guid>http://blog.jenkster.com/2015/02/a-brief-and-partial-review-of-haskell-in-the-browser.html</guid>
		  <description>&lt;p&gt;Ah, the browser. Like iOS, it’s a place of pleasure and pain. Love the
audience it reaches; hate the default language. So I have a keen interest in
the rise of “Compiles to JavaScript” languages. ClojureScript is my
current weapon of choice, and I’m very happy with it. But I’ve also
spent a chunk of time researching Haskell-like options for the
browser, and I thought I’d write up my experiences.&lt;/p&gt;

&lt;p&gt;Before we begin, for context, here is:&lt;/p&gt;

&lt;h2 id=&quot;what-im-looking-for-in-a-browser-language&quot;&gt;What I’m Looking For In A Browser Language&lt;/h2&gt;

&lt;h3 id=&quot;sane-language-design&quot;&gt;Sane language design&lt;/h3&gt;
&lt;p&gt;That rules out JavaScript, CoffeeScript, TypeScript, ScalaJS and several others.&lt;/p&gt;

&lt;h3 id=&quot;separation-of-logic--rendering&quot;&gt;Separation of logic &amp;amp; rendering&lt;/h3&gt;

&lt;p&gt;If your onClick handler references business-logic functions directly,
something is wrong.&lt;/p&gt;

&lt;h3 id=&quot;no-manual-dom-manipulation&quot;&gt;No manual DOM manipulation&lt;/h3&gt;
&lt;p&gt;Are you still doing that? Stop it. Unless you enjoy manual memory
management too. (In which case good luck to you, my fine retronaught.)&lt;/p&gt;

&lt;h3 id=&quot;no-callbacks&quot;&gt;No callbacks&lt;/h3&gt;

&lt;p&gt;Our brains are happiest with a single line of control flow. Yes you
can get comfortable with callback-passing, but it never sits as easily
as not having to. And like DOM manipulation, you don’t have to
anymore. It’s a job for the language, not for you. Save your brain.&lt;/p&gt;

&lt;h2 id=&quot;the-players&quot;&gt;The Players&lt;/h2&gt;

&lt;h3 id=&quot;ghcjs&quot;&gt;GHCJS&lt;/h3&gt;

&lt;p&gt;GHCJS reuses the GHC compiler we all know &amp;amp; love, but modifies it to
emit JavaScript. The result is extremely impressive. You really do get
a full Haskell experience. The language features are the same, the
compiler messages the same, even most stuff on Hackage just
works. It’s good.&lt;/p&gt;

&lt;p&gt;I’ve heard people complain about the size of the JS files it
produces. Apparently in the early days it was particularly bad, but to
me, now, it seems perfectly acceptable. Once a production webapp will
minify &amp;amp; gzip to less than the size of an animated cat gif, it’s time
to stop yapping about file sizes.&lt;/p&gt;

&lt;p&gt;There were three downsides with GHCJS for me. The first is, how should
you structure a full client-side app? &lt;a href=&quot;https://github.com/krisajenkins/bellringer&quot;&gt;I did some work on this with Ben Ford&lt;/a&gt;, and then he &lt;a href=&quot;https://github.com/boothead/ohm&quot;&gt;took it much further&lt;/a&gt;, but it’s still very much an
area of research. I couldn’t say to anyone, “This is the way to build
it; you’ll need these pieces.”&lt;/p&gt;

&lt;p&gt;The second problem is that GHCi isn’t supported yet. Without that, I
found incremental build times to be just a bit too long, even for a
small app.&lt;/p&gt;

&lt;p&gt;And the third problem, and for me the nail in the coffin, is it’s a
real pain to install. If you thought cabal hell was hell, I can tell
you there’s another layer of problems lying in wait. Honestly, I
couldn’t even say to anyone, “You should try GHCJS.” Getting started is
asking too much.&lt;/p&gt;

&lt;p&gt;All these problems will be addressed, and quickly I expect. Simply
because of the quality of compiler, GHCJS is the one to watch. But
I’ve put it aside for now.&lt;/p&gt;

&lt;h3 id=&quot;haste&quot;&gt;Haste&lt;/h3&gt;

&lt;p&gt;If not GHCJS, how about another, “Let’s make regular GHC emit
JavaScript!” approach? That’s what Haste does.&lt;/p&gt;

&lt;p&gt;I liked Haste initially, until I got to that absolutely necessary
evil, JavaScript interop, and everything fell apart. I recall I wanted
to share a simple list of integers between Haste and JavaScript, and I
couldn’t do it. The official position seems to be, “Yes, it ought to
be easy. If you have a patch I’ll merge it.”&lt;/p&gt;

&lt;p&gt;If Haste needs serious expertise to pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2, 3]&lt;/code&gt;, then it’s not for me.&lt;/p&gt;

&lt;h3 id=&quot;purescript&quot;&gt;PureScript&lt;/h3&gt;

&lt;p&gt;PureScript moves us away from GHC and into languages that are
styled-after Haskell. PureScript seems to be winning a popular vote
(in this ultra-niche), and I can see why. The language has the
headline features from Haskell, interop is good, it all works, and the
documentation is excellent.&lt;/p&gt;

&lt;p&gt;There are a few downsides for me that eventually stacked up too
high. Tooling’s a bit of a pain. (You’ll need Node. And Grunt. And
Bower. Wait, are we actually building a JavaScript project?)&lt;/p&gt;

&lt;p&gt;The compiler errors are…disappointing. Haskell development leans
heavily on fast, high-quality feedback from the type system. If you
squint, the GHC compiler is almost a REPL. From what I gather, GHC has
taken a vast amount of engineering effort to get to where it is, so
you can’t blame PureScript for lagging behind. But lag it does, and
when PureScript spits out a type error, I feel very much alone.&lt;/p&gt;

&lt;p&gt;And finally, the “how do we structure/how do we render?” question felt
unanswered. There is a virtual DOM library, but it was scrappy. I
didn’t have an Om-quality experience using it. I’m sure it will
get better, but like GHCJS it feels like an untrodden path.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bonus Tip: If you’re playing with PureScript, Take a look at &lt;a href=&quot;https://github.com/bodil/pulp&quot;&gt;Bodil Stokke’s Pulp&lt;/a&gt; for your building needs. That worked well for me.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;elm&quot;&gt;Elm&lt;/h3&gt;

&lt;p&gt;Elm is nice. Very nice. The language is good. Control flow is
sane. The documentation is expansive (though more scattered about than
PureScript). Incremental compilation times are pleasing. The compiler
feedback is good. (No GHC, but better than PureScript.) Interop is so
easy it makes you wonder why interop is hard.&lt;/p&gt;

&lt;p&gt;The tooling’s excellent, even before you get into the fancy stuff like
the time-travelling debugger. You can just write some code, compile it
in seconds, get a single page you can upload straight to S3, and your
website’s running. And the path from that to a proper minified,
production app is smooth enough.&lt;/p&gt;

&lt;p&gt;I’ve heard people say Elm is great for game-like things, but little
attention has been given to regular HTML apps. That’s not true. The
&lt;a href=&quot;https://github.com/evancz/elm-html&quot;&gt;elm-html&lt;/a&gt; library is, give or take, a perfect substitute for Om/React.&lt;/p&gt;

&lt;p&gt;And the FRP approach may prove a bit of a learning curve for some, but
I found it very natural. There’s a certain way that I’ve been
structuring my ClojureScript apps, and Elm feels like it’s taking the
same route, but has baked it into the language. I heartily approve.&lt;/p&gt;

&lt;p&gt;On the downside, I do really wish it had typeclasses. And not even for
shiny things like putting my monoids in the category of
endofunctors. Just for simple stuff. Having to qualify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List.map&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Signal.map&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set.map&lt;/code&gt; gets old very quickly. And Json decoding
would be much simpler if it supported return-type polymorphism.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As you can probably guess, for now I’ve settled on Elm. I’m building
an MVP for a startup of my own at the moment, and the front end is
Elm. I’ll let you know how it goes.&lt;/p&gt;

&lt;p&gt;Oh, and I’ll be keeping my eye on GHCJS…&lt;/p&gt;

&lt;h2 id=&quot;coda&quot;&gt;Coda&lt;/h2&gt;

&lt;p&gt;Last week I went to an Elm night at Twitter HQ and Tom Ashworth was
speaking. I asked him if he thought Elm was ready for production. He
said no. I wish I’d also asked if he thought JavaScript was ready for
production… :-)&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Backwards Compatibility Testing For Your Clojure Project</title>
		  <pubDate>Thu, 20 Feb 2014 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2014/02/backwards-compatibility-testing-your-clojure-project.html</link>
		  <guid>http://blog.jenkster.com/2014/02/backwards-compatibility-testing-your-clojure-project.html</guid>
		  <description>&lt;p&gt;Leiningen makes it really easy to test your project against multiple
versions of Clojure. Really staggeringly easy. Like, “I don’t know a
single other language where this is so seamless,” easy. It’s a little
trick I picked up from &lt;a href=&quot;http://clojure.github.io/java.jdbc/&quot;&gt;clojure.java.jdbc&lt;/a&gt;, and I make good use of it in
&lt;a href=&quot;https://github.com/krisajenkins/yesql&quot;&gt;Yesql&lt;/a&gt;. Here’s how it goes:&lt;/p&gt;

&lt;p&gt;Since version 2, Leiningen lets you specify multiple profiles, with
their own dependency lists. What’s interesting is that Clojure itself
can be one of those dependencies, so we can meaningfully add this to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.clj&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;:profiles&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:1.4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:dependencies&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;org.clojure/clojure&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.4.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:1.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:dependencies&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;org.clojure/clojure&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.5.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:1.6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:dependencies&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;org.clojure/clojure&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.6.0-beta1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]}}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lein with-profile +1.4 test&lt;/code&gt; means “run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lein test&lt;/code&gt; under
default profile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt;, &lt;em&gt;plus&lt;/em&gt; merge in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.4&lt;/code&gt; profile”. Upshot: the
code runs as normal, but under Clojure 1.4.&lt;/p&gt;

&lt;p&gt;Now just add this alias:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;:aliases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test-all&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;with-profile&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;+1.4:+1.5:+1.6&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lein test-all&lt;/code&gt; will run the test suite three times, under each
of Clojure 1.4, 1.5 and 1.6, automatically.&lt;/p&gt;

&lt;p&gt;You can use that same trick for any dependency variations you like -
so you could check against different versions of your database driver,
for instance - but it’s this 4-line use case that really made my jaw
drop.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>An Elegant Little core.async Solution</title>
		  <pubDate>Thu, 20 Feb 2014 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2014/02/an-elegant-little-coreasync-solution.html</link>
		  <guid>http://blog.jenkster.com/2014/02/an-elegant-little-coreasync-solution.html</guid>
		  <description>&lt;p&gt;Yesterday I had a problem that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.async&lt;/code&gt; provides an incredibly neat
solution to. Tim Baldridge was kind enough to sanity check it for me,
so I thought I’d write it up.&lt;/p&gt;

&lt;p&gt;Imagine you want to process a message at a maximum rate of one per
second. In another language you’d probably say something like:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;process_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;end_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;elapsed_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elapsed_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elapsed_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not hard to write, of course, but kinda clumsy. Here’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.async&lt;/code&gt;
version:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;process-message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;lt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In English, pick up a ticket that lasts for 1000 milliseconds; process
a message; wait until the ticket expires.  If processing the message
took more than 1000ms, the ticket returns immediately, otherwise it
blocks for the remaining time.&lt;/p&gt;

&lt;p&gt;Simple &lt;em&gt;and&lt;/em&gt; easy. A really neat solution.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Using Joda Time as your Clojure inst Class</title>
		  <pubDate>Sat, 08 Feb 2014 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2014/02/using-joda-time-as-your-clojure-inst-class.html</link>
		  <guid>http://blog.jenkster.com/2014/02/using-joda-time-as-your-clojure-inst-class.html</guid>
		  <description>&lt;p&gt;In Clojure, the reader-literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#inst&lt;/code&gt; reads &amp;amp; writes
java.util.Dates. For instance:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inst&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2014-02-06T00:00:00Z&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;=&amp;gt; java.util.Date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pr-str&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;java.util.Date.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;=&amp;gt; #inst &quot;2014-02-08T15:54:49.949-00:00&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But it’s possible to replace that behaviour to read and write Joda
time instances. Here’s how:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER&lt;/em&gt; This may be a terrible idea. In fact it probably is. Go
 away, unless you enjoy standing in the middle of a thunderstorm
 cackling, “It’s Alive! It’s Alive!”&lt;/p&gt;

&lt;p&gt;Still with me? That’s the spirit!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;First&lt;/em&gt; you’ll need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clj-time&lt;/code&gt;. Add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.clj&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:dependencies&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clj-time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.6.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Second&lt;/em&gt; To get Clojure to read #insts as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.joda.time.DateTime&lt;/code&gt; classes, add this to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/data_readers.clj&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inst&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clj-time.format/parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That just switches out the function that turns strings into date
objects. Restart your REPL session to pick that up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Third&lt;/em&gt; You’ll need to implement a printing method, so that the classes
are written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#inst&lt;/code&gt;-tagged strings:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print-dup&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;org.joda.time.DateTime&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.write&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#inst \&quot;%s\&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure that code’s been imported into any namespace where you want
this to work. Now you can say:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:start&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inst&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2014-02-06T00:00:00.000-00:00&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inst&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2014-02-06T02:00:00.000-00:00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And get a map whose values are Joda &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;As I say, this is probably a bad idea. It’ll unexpectedly break things
for people. But it’s a fun hack anyway, so I thought I’d record it.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Our Total Quality Approach to Software</title>
		  <pubDate>Sat, 25 Jan 2014 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2014/01/our-total-quality-approach.html</link>
		  <guid>http://blog.jenkster.com/2014/01/our-total-quality-approach.html</guid>
		  <description>&lt;p&gt;Here at CueCorp Ltd. we have a total approach to software Quality,
experimenting with every possible angle to maximize shareholder value.&lt;/p&gt;

&lt;p&gt;Our &lt;em&gt;Quality Insurance&lt;/em&gt; department collects a regular monthly premium
from our developers. In the event that bad code gets released to
production, the devs put in a claim and get sent a cheque to cover the
cost of fixing it. Premiums are climbing, but we have high hopes for
this innovative, market-driven approach to Quality.&lt;/p&gt;

&lt;p&gt;Our &lt;em&gt;Quality Assurance&lt;/em&gt; department wanders around the office daily,
talking to devs, managers and all other staff, confidently assuring
them that the software will work. We’re not 100% sure of the value of
this, but we checked the dictionary and it confidently assured us that
that’s what ‘assurance’ means.&lt;/p&gt;

&lt;p&gt;Our &lt;em&gt;Quality Ensurance&lt;/em&gt; department is our most successful arm. Though
their remit is wide, they take every angle and every opportunity to
ensure the quality of our software. By writing test suites,
by training our devs, by explaining the value of refactoring to our
management team, by working with our architects to choose simpler and
more reliable tools - there is no approach they won’t try to ensure
that they ensure what they’re supposed to ensure.&lt;/p&gt;

&lt;p&gt;Obviously, Quality is our highest priority, and our structure is an
ongoing experiment. If you care more about software Quality than
labels, rest assured (ensured? insured?) there’s a place for you here
at CueCorp!&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Book Review - Clojure for Domain Specific Languages</title>
		  <pubDate>Sat, 18 Jan 2014 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2014/01/book-review-clojure-for-domain-specific-languages.html</link>
		  <guid>http://blog.jenkster.com/2014/01/book-review-clojure-for-domain-specific-languages.html</guid>
		  <description>&lt;p&gt;What a great title, eh? Clojure’s a fantastic language for writing
DSLs, and yet it’s a hard topic get into. A good book on the subject
is just what the Clojure ecosystem needs.&lt;/p&gt;

&lt;p&gt;Sadly, this isn’t that book.&lt;/p&gt;

&lt;p&gt;The biggest problem is that there’s hardly any content about writing
DSLs. This is a ~240 page book, and about 200 of that is just “Intro
to Clojure” stuff. That would be fine, but there are much better
introductory books out there.&lt;/p&gt;

&lt;p&gt;Filler aside, that leaves maybe 40 pages that are actually about writing
DSLs. Sadly it’s the weakest stuff in the book. It consists of two
examples of using Clojure to wrap existing Java libraries. One’s a
Twitter client, the other’s a wrapper around Java’s Date &amp;amp; Calendar
classes. And there’s no way around saying this - both are badly written.&lt;/p&gt;

&lt;p&gt;It would be a terrible shame if any beginner in Clojure read this
stuff and thought it was a good way to proceed.  What should be a
simple function to read a config file into a map is presented in an
overwrought &amp;amp; brittle fashion.  Macros are used frequently but never
appropriately.  Clojure code drops down into Java interop for no good
reason at all.  And the author seems to have an obsession with
dynamically-binding variables, regardless of whether it’s appropriate.
I strongly suspect this betrays a lack of understanding about what
they’re for. Either way, the Twitter DSL is going to break as soon as
you do anything interesting with it, like delay the results. (Stuart
Sierra has &lt;a href=&quot;http://stuartsierra.com/2013/03/29/perils-of-dynamic-scope&quot;&gt;a great post about it&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;So is there anything here to like? Yes, the author is quite lucid. His
technical writing reads easily. I hope he writes a book on another
topic one day - but he’ll need to be far better versed in the
material.&lt;/p&gt;

&lt;p&gt;In the meantime, if you want an intro to Clojure book, check out the
superb &lt;a href=&quot;http://www.amazon.com/gp/product/1935182641/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1935182641&amp;amp;linkCode=as2&amp;amp;tag=blogjenksterc-20&quot;&gt;Joy of Clojure&lt;/a&gt;. And if you’re a seasoned Clojure programmer
looking for a good book on DSL writing…well…so am I. In the
meantime, &lt;a href=&quot;http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure&quot;&gt;here’s a good article&lt;/a&gt; on one application of the technique…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Tech I Want To Build/Learn In 2014</title>
		  <pubDate>Tue, 31 Dec 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/12/tech-2014.html</link>
		  <guid>http://blog.jenkster.com/2013/12/tech-2014.html</guid>
		  <description>&lt;p&gt;Last day of 2013, and it’s time to look ahead to the year to
come. Here are my tech aims for 2014:&lt;/p&gt;

&lt;h2 id=&quot;learn-haskell&quot;&gt;Learn Haskell&lt;/h2&gt;

&lt;p&gt;I decided last year I wasn’t going to learn any new
languages&lt;sup id=&quot;fnref:scala&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:scala&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Instead I was going to double down &amp;amp; get &lt;em&gt;really
tasty&lt;/em&gt; at Clojure. There’s still plenty of deliciousness left in that
journey, but I think I’ve done well enough to pick up a little
something new.&lt;/p&gt;

&lt;p&gt;But what new thing should I choose? Well, probably the best advice I
heard all year was from &lt;a href=&quot;https://twitter.com/sanityinc&quot;&gt;Steve Purcell&lt;/a&gt;, which I’ll paraphrase as,
“Figure out what the smartest, nicest people you can find are
learning, and learn that.” I look around and see Clojure &amp;amp; Haskell
fitting that description, so it feels like the time is coming.&lt;/p&gt;

&lt;p&gt;(Actually, Haskell isn’t new to me. It’s just my Haskell skills are so
crusty as to earn a seat in the House of Lords. A 15-year hiatus, by my
calculations.)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chances of it happening&lt;/em&gt;: Strong. I love a new language. Would be nice
if I had a commercial reason to motivate it though.&lt;/p&gt;

&lt;h2 id=&quot;write-a-good-database-reporting-system&quot;&gt;Write A Good Database Reporting System&lt;/h2&gt;

&lt;p&gt;Reports servers, universally, suck. In roughly-chronological order,
I’ve used Oracle Reports, BIRT, Oracle Apex, JasperReports &amp;amp; Crystal
Reports, and not one of them has shed a glimmer of hope. They’re
tolerable, but they’re not good.&lt;/p&gt;

&lt;p&gt;Here’s a test you can apply to see if your report-server sucks: Which
is easier? Adding a pink circle to the top-left corner of a report, or
adding a new column to it and pushing it live?&lt;/p&gt;

&lt;p&gt;The fact that it’s easier to find the ellipse button than the deploy
button is proof that something is tragically wrong.&lt;/p&gt;

&lt;p&gt;I know why they all suck. I know exactly why. It’s because they’re
designed on a lie. The lie is, “Use our tool and you can just drag &amp;amp;
drop reports together. You’ll never need to learn SQL and you’ll never
need to ask IT again.”&lt;/p&gt;

&lt;p&gt;BS. Never happens. Putting a drag &amp;amp; drop interface on it doesn’t save
you from learning the database schema, so the job gets pushed to IT
anyway. Except now you’ve spent a packet on forcing a dumbed-down
interface on people who’d be happier with SQL and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt;.  If we
assumed the report-reader was non-technical, but the &lt;em&gt;report-writer&lt;/em&gt; was
a geek, we could get the turnaround time on new reports down to less
than half an hour. And everyone would be happier.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chances of it happening&lt;/em&gt;: Unknown. I can see how to build it. I believe
it’s commercially viable. But I can’t see how to market it. That’s
something to mull.&lt;/p&gt;

&lt;h2 id=&quot;write-an-edn-parser-for-emacs&quot;&gt;Write an EDN Parser for Emacs&lt;/h2&gt;

&lt;p&gt;I’ve been playing around with a few CIDER tricks lately - such as &lt;a href=&quot;http://blog.jenkster.com/2013/12/a-cider-excursion.html&quot;&gt;this bind-a-Clojure-command&lt;/a&gt;
tip - to improve my Clojure-on-Emacs workflow. I could do some far
cooler stuff if Emacs could read Clojure data structures, and an EDN
parser’s the route to that.&lt;/p&gt;

&lt;p&gt;For instance, I’m thinking a much better org-babel/Clojure
integration&lt;sup id=&quot;fnref:babel&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:babel&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; for starters. After that, I’d love to have a
buffer that pretty-prints the value of an atom, watches it for
changes, and does some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watch&lt;/code&gt;-style syntax-highlighting for any diffs.
That would rock.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chances of it happening&lt;/em&gt;: Good. Geeky confession: I enjoy writing
parsers. And I’m always buggering around with Emacs these days, so
it’s probably just a matter of time.&lt;/p&gt;

&lt;h2 id=&quot;write-an-editor&quot;&gt;Write An Editor&lt;/h2&gt;

&lt;p&gt;If you’ve been here before you’ve probably gathered that I’m an editor
junkie, and there’s a constant pull to scratch my own itch. My ideal
editor would be a mashup of these principles:&lt;/p&gt;

&lt;h3 id=&quot;treat-the-user-like-a-programmer-the-way-emacs-does&quot;&gt;Treat The User Like A Programmer, The Way Emacs Does.&lt;/h3&gt;
&lt;p&gt;Why is Emacs the only programming tool that assumes you’ll want to
program it? Sure, almost every editor has some means of extension, but
Emacs really is in a different league. It opens on a “Program Me!”
buffer for chrissakes.&lt;/p&gt;

&lt;p&gt;(If you don’t believe Emacs is &lt;em&gt;uniquely&lt;/em&gt; extensible, check out my
video, &lt;a href=&quot;post:2013-10-08-writing-a-spotify-client-in-16-minutes&quot;&gt;Writing A Spotify Client in 16 Minutes&lt;/a&gt;.)&lt;/p&gt;

&lt;h3 id=&quot;treat-the-user-like-an-expert-the-way-vim-does&quot;&gt;Treat The User Like An Expert, The Way Vim Does.&lt;/h3&gt;

&lt;p&gt;For any tool you’ll use for 40 hours a week, for the next decade, the
initial learning curve is irrelevant. It’s how productive it makes you
after the first month that counts.&lt;/p&gt;

&lt;h3 id=&quot;treat-the-world-like-its-the-21st-century-the-way-lighttable-does&quot;&gt;Treat The World Like It’s The 21st Century, The Way LightTable Does.&lt;/h3&gt;

&lt;p&gt;In short, I would trade terminal support for an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chances of it happening&lt;/em&gt;: Slim, sadly. Writing a good editor - and a
good one is the only kind I have any interest in writing - is a long,
long road. Unless it can pay its way, I’m going to have to resist
going down that rabbit hole.&lt;/p&gt;

&lt;h2 id=&quot;find-a-day-job&quot;&gt;Find A Day Job&lt;/h2&gt;

&lt;p&gt;2013 has been something of a sabbatical year for me. It’s been
fantastic for feeding my brain, but too isolated, and if I’m brutally
honest, a little navel-gazing. I’ve decided to &lt;a href=&quot;pdf:Kris_Jenkins_CV.pdf&quot;&gt;brush up my CV&lt;/a&gt; and
find some smart people to build interesting things with. I did a few
contracts last year, and there is something delightful about building
to spec. This year I’m going to dive in with both feet.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chances of it happening&lt;/em&gt;: Strong. Tell me if you know of any
interesting opportunities!&lt;/p&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:scala&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Okay, I tripped up &amp;amp; fell into Scala, but I got back up quickly. &lt;a href=&quot;#fnref:scala&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:babel&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Better than &lt;a href=&quot;http://blog.jenkster.com/2013/02/org-babel-clojure-and-nrepl.html&quot;&gt;this quick fix&lt;/a&gt; at least! &lt;a href=&quot;#fnref:babel&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Popup Help In Emacs Lisp</title>
		  <pubDate>Sat, 28 Dec 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/12/popup-help-in-emacs-lisp.html</link>
		  <guid>http://blog.jenkster.com/2013/12/popup-help-in-emacs-lisp.html</guid>
		  <description>&lt;p&gt;If you use Clojure &amp;amp; Emacs, you probably use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ac-nrepl-popup-doc&lt;/code&gt; to get
the docs for the thing under the point, in a temporary popup
window. And if you write any Elisp, you might be hankering for the
same thing for Emacs’ docs.&lt;/p&gt;

&lt;p&gt;Here’s some code that displays the same text as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;describe-function&lt;/code&gt;, but
in a popup overlay:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;describe-function-in-popup&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;symbol-at-point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;save-window-excursion&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;describe-function&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;switch-to-buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*Help*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buffer-string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;popup-tip&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;description&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:around&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:height&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:scroll-bar&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:margin&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code is actually fairly simple, so let’s break it down:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol-at-point&lt;/code&gt; picks up the thing under the cursor, which should be
the function you’re hovering over.&lt;/p&gt;

&lt;p&gt;The shenannigens inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save-window-excursion&lt;/code&gt; is just opening the
regular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;describe-function&lt;/code&gt; window, snarfing its contents, and then
closing it immediately. That puts the help text in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we just call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;popup-tip&lt;/code&gt; to display it. Here’s a screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/describe-function-popup.png&quot; alt=&quot;Popup Emacs Help&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You’ll probably want to set up your own favourite keybinding, but
here’s one example, binding it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-5&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-set-key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'describe-function-in-popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;update&quot;&gt;Update&lt;/h2&gt;

&lt;p&gt;Thanks to a comment from &lt;a href=&quot;https://twitter.com/sanityinc&quot;&gt;Steve Purcell&lt;/a&gt;, we can refine this to work for
variables &amp;amp; faces, not just functions. The big change here is that we
replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;describe-function&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;help-xref-interned&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;describe-thing-in-popup&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;symbol-at-point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;help-xref-following&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with-temp-buffer&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;help-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;help-xref-interned&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buffer-string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;popup-tip&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;description&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:around&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:height&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:scroll-bar&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
               &lt;span class=&quot;ss&quot;&gt;:margin&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One of the nice things about this change is that help-xref lets us
supply our own temporary buffer, instead of re-using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*Help*&lt;/code&gt;. That
means we don’t clobber anything that’s currently in your help buffer.&lt;/p&gt;

&lt;p&gt;To take advantage of that, we just need to set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;help-xref-following&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;, and put the temp buffer in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;help-mode&lt;/code&gt;.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Clojure On Emacs - A CIDER Workflow Hack</title>
		  <pubDate>Sat, 28 Dec 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/12/a-cider-excursion.html</link>
		  <guid>http://blog.jenkster.com/2013/12/a-cider-excursion.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;TLDR; In a few lines of Emacs Lisp, you can speed up your Clojure workflow, and it’s easy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently I’ve been experimenting with &lt;a href=&quot;https://github.com/clojure/tools.namespace&quot;&gt;clojure.tools.namespace&lt;/a&gt; and
&lt;a href=&quot;http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded&quot;&gt;Stuart Sierra’s Reloaded Workflow&lt;/a&gt;. If you haven’t read that post, you
should add it to your reading list. It’s a smart way of adding a
reset button to your REPL session, to ensure a clean environment
without having to restart the JVM.&lt;/p&gt;

&lt;p&gt;This post isn’t really about that workflow &lt;em&gt;per se&lt;/em&gt;, it’s just a good
use-case to demonstrate a little Emacs/Clojure/CIDER-fu.&lt;/p&gt;

&lt;p&gt;If you adopt that workflow, you’ll find yourself repeatedly typing
this into the REPL:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;'clojure.tools.namespace.repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clojure.tools.namespace.repl/refresh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are a few ways to save that typing, but a little Emacs Lisp is
the most satisfying.&lt;/p&gt;

&lt;h2 id=&quot;its-simple&quot;&gt;It’s Simple&lt;/h2&gt;

&lt;p&gt;The easiest way in is to use the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cider-interactive-eval&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cider-namespace-refresh&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cider-interactive-eval&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;&quot;(require 'clojure.tools.namespace.repl)
      (clojure.tools.namespace.repl/refresh)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure-mode-map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'cider-namespace-refresh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x cider-namespace-refresh&lt;/code&gt;, or simply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-r&lt;/code&gt;, will run our Clojure
string and hit the reset button. Job done.&lt;/p&gt;

&lt;h2 id=&quot;its-reusable&quot;&gt;It’s Reusable&lt;/h2&gt;

&lt;p&gt;It doesn’t take much imagination to see how we can re-use this code.&lt;/p&gt;

&lt;p&gt;Say this afternoon’s development task means you’re going to be looking
at the value of an atom a lot. These few lines put viewing that atom a
single keystroke away:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure-mode-map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cider-interactive-eval&lt;/span&gt;
         &lt;span class=&quot;s&quot;&gt;&quot;(require '[clojure.pprint :refer [pprint]])
          (pprint @interesting-atom)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s a recipe for a function you can set up in a heartbeat, and throw
away after a much zippier afternoon.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Emacs - Reindent The Whole Buffer</title>
		  <pubDate>Thu, 26 Dec 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/12/emacs-reindent-the-whole-buffer.html</link>
		  <guid>http://blog.jenkster.com/2013/12/emacs-reindent-the-whole-buffer.html</guid>
		  <description>&lt;p&gt;Quite often in Emacs, especially when writing Clojure code, I want to
reindent the entire file. I think that arises from the fact that I’m
writing a lot of Lisp these days, and Lisp is the only language I’ve
ever encountered where automatic indenting actually works well.&lt;/p&gt;

&lt;p&gt;Anyway, here’s the code I use to map &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meta-shift-q&lt;/code&gt; to “reindent the
whole buffer”:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reindent-whole-buffer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Reindent the whole buffer.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;indent-region&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-set-key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-Q&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'reindent-whole-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pretty simple, huh?&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>A Tip About Clojure's Less Than &amp; Greater Than Operators</title>
		  <pubDate>Wed, 27 Nov 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/11/clojure-less-than-greater-than-tip.html</link>
		  <guid>http://blog.jenkster.com/2013/11/clojure-less-than-greater-than-tip.html</guid>
		  <description>&lt;p&gt;Although it initially takes some getting used to, I think
Clojure/Lisp’s prefix operators are a great idea. They make multi-argument
functions really easy, so you can say things like:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…instead of the much-clunkier:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After a while you start to wonder why languages bother with operators
that are limited to two arguments.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; variants are equally cool, as you can do things like
replace the classic range-check:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…with:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But in the early days, I found it hard to remember whether I wanted
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;lt; x 2)&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;gt; x 2)&lt;/code&gt;. For the simple pair, greater-than or less-than
just seemed to naturally belong in the middle, for the visual reminder.&lt;/p&gt;

&lt;p&gt;So here’s my mind-hack tip: Think of them as ‘getting-larger’ and
‘getting-smaller’ operators, and look at the shapes of the characters.&lt;/p&gt;

&lt;p&gt;The glyph &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; is a triangle that starts small on the left and gets
larger as it goes right. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;lt; 2 x)&lt;/code&gt; is checking if the arguments start
small on the left, and get larger as you go right. Two is small, x is
larger.&lt;/p&gt;

&lt;p&gt;Similarly for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;. It starts large on the left of the shape &amp;amp; gets
smaller as it goes right.&lt;/p&gt;

&lt;p&gt;I found that helped the penny drop for me. Hopefully it’ll help a
reader or two…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Dear Starbucks, I Like Clojure</title>
		  <pubDate>Wed, 23 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/dear-starbucks-i-like-clojure.html</link>
		  <guid>http://blog.jenkster.com/2013/10/dear-starbucks-i-like-clojure.html</guid>
		  <description>&lt;p&gt;Dear Starbucks,&lt;/p&gt;

&lt;p&gt;I like Clojure. It’s a relatively new JVM-based language in the family
of Lisp languages, which puts it in a heritage that’s practically as
old as programming itself.&lt;/p&gt;

&lt;p&gt;It favours modelling problems using simple, immutable data
structures - and let me tell you, once you’ve got used to immutable
data structures you’ll never want to go back to a language without
them.&lt;/p&gt;

&lt;p&gt;It uses a syntax that’s akin to writing your code directly as an AST,
which enables some very handy language features and editing tricks and
again, will be hard to give up once you’ve gotten used to it.&lt;/p&gt;

&lt;p&gt;And it has a REPL-driven development model that give you such a tight
feedback loop on your code it’s more like you’re having a conversation
with your computer - one that results in working code. It’s so much
fun.&lt;/p&gt;

&lt;p&gt;And that reaction you have right now, the one that says, “I’m glad
you’re happy, but I don’t know what you’re talking about and I don’t
really care so please just quietly get on with whatever you do best
without telling me the details ever again.”&lt;/p&gt;

&lt;p&gt;That’s how I feel when you ask me which kind of coffee bean I want.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Getting the Bleeding Edge Build of an Emacs MELPA Package</title>
		  <pubDate>Tue, 15 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/getting-the-bleeding-edge-build-of-an-emacsmelpa-package.html</link>
		  <guid>http://blog.jenkster.com/2013/10/getting-the-bleeding-edge-build-of-an-emacsmelpa-package.html</guid>
		  <description>&lt;p&gt;Today I learnt a great tip &lt;a href=&quot;https://github.com/clojure-emacs/nrepl.el/issues/382][here]] via [[http://www.sanityinc.com/&quot;&gt;Steve Purcell&lt;/a&gt;. If you want to get
the absolute latest build of an Emacs package, without waiting for the
MELPA rebuild cycle to take place, just:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Clone &lt;a href=&quot;https://github.com/milkypostman/melpa.git&quot;&gt;the Melpa repo&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipes/&lt;/code&gt; file in emacs.&lt;/li&gt;
  &lt;li&gt;Accept the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir-locals&lt;/code&gt; warning.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x package-build-current-recipe&lt;/code&gt; to evaluate that recipe locally and install the latest package.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I must remember that one…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Using OAuth2 with Emacs</title>
		  <pubDate>Sun, 13 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/an-oauth2-in-emacs-example.html</link>
		  <guid>http://blog.jenkster.com/2013/10/an-oauth2-in-emacs-example.html</guid>
		  <description>&lt;p&gt;I’ve been playing with the GitHub API, through Emacs. For all the
interesting stuff, it needs OAuth2 authorization, and though there’s
good support in Emacs for OAuth2, I couldn’t find a getting started
guide. So, here goes:&lt;/p&gt;

&lt;p&gt;First you’ll need an access token. The standard way of getting an
access token - redirect to the service (Github), authorize, redirect
back to your website - isn’t going to help us much. We don’t have a
website to come back to. It’s just an Emacs client.
But there’s an alternative, and all the providers I’ve played around
with so far support it. They’ll issue you an access token manually
for personal use.&lt;/p&gt;

&lt;p&gt;So, we head off to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Github &amp;gt; Account Settings &amp;gt; Applications&lt;/code&gt; and
there’s a box marked “Personal Access Tokens”. Creating one of those
gives us a token like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8914803c3f5038531dec13166ce098710c649281&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that magic string we’re away. Require the package (you may need
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x package-install&lt;/code&gt; it first), then create an oauth2-token struct:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'oauth2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-token&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;make-oauth2-token&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:access-token&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;8914803c3f5038531dec13166ce098710c649281&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that we turn to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oauth2-url-retrieve-synchronously&lt;/code&gt;. It will take
a token and a url and return a buffer containing the HTTP response. We
can dip into that buffer and read the JSON like this:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-data&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with-current-buffer&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;oauth2-url-retrieve-synchronously&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-token&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://api.github.com/user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;goto-char&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url-http-end-of-headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;json-read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Job done. Let’s just pull out an item:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Kris Jenkins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s all there is to it. (Or at least, enough to get you started…)&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Writing a Spotify Client in 16 Minutes</title>
		  <pubDate>Tue, 08 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/writing-a-spotify-client-in-16-minutes.html</link>
		  <guid>http://blog.jenkster.com/2013/10/writing-a-spotify-client-in-16-minutes.html</guid>
		  <description>&lt;iframe width=&quot;640&quot; height=&quot;480&quot; src=&quot;//www.youtube.com/embed/XjKtkEMUYGc&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;And the &lt;a href=&quot;https://github.com/krisajenkins/helm-spotify&quot;&gt;code is on Github&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Finding Files In Emacs Helm</title>
		  <pubDate>Tue, 08 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/finding-files-in-emacs-helm.html</link>
		  <guid>http://blog.jenkster.com/2013/10/finding-files-in-emacs-helm.html</guid>
		  <description>&lt;p&gt;Emacs’ &lt;a href=&quot;https://github.com/emacs-helm/helm&quot;&gt;Helm&lt;/a&gt; is awesome. (I’m on a bit of a helm kick this week). You
can &lt;a href=&quot;http://blog.jenkster.com/2013/10/writing-a-spotify-client-in-16-minutes.html][use it to write a Spotify client]], you can [[http://blog.jenkster.com/2013/10/a-tip-for-navigating-clojure-files-in-emacs.html&quot;&gt;use it as a code-browser&lt;/a&gt;, but you can also use it for simple things like finding
files in a directory, tree or project.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;The setup’s pretty easy. You’ll want to install it of course:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;M-x package-install
helm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.emacs&lt;/code&gt; and kick it off:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;

&lt;p&gt;Most helm stuff involves calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(helm ...)&lt;/code&gt; function with some named
arguments. Once you’ve found the ones you want, you’ll want to bind it
to a shortcut key, but for now let’s try a basic invocation from the
scratch buffer.&lt;/p&gt;

&lt;p&gt;The two named arguments I use most are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sources&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:buffer&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sources&lt;/code&gt;
gives helm a list of places it can find search candidates. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:buffer&lt;/code&gt;
just names the buffer.&lt;/p&gt;

&lt;h2 id=&quot;some-searchy-examples&quot;&gt;Some Searchy Examples&lt;/h2&gt;

&lt;p&gt;So, a simple way to search for files under the current directory is:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-source-findutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*helm-findutils*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’ll wait for you to enter at least 4 characters to narrow things
down, then present a list.&lt;/p&gt;

&lt;p&gt;We can add to that a few extra file-finding sources. If you
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package-install&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helm-ls-git&lt;/code&gt;, you can search the git project for the
current file:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-source-ls-git&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*helm-find-git*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you’re using Linux or OSX, you can search machine-wide through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locate&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-source-locate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*helm-locate*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mix--match&quot;&gt;Mix &amp;amp; Match&lt;/h2&gt;

&lt;p&gt;And rather cool, you can mix all three of these sources, in whichever
order you prefer:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-source-findutils&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-ls-git&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-locate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*helm-find-files*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each section will be filtered separately, and you can jump between
them with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-o&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;more-than-you-asked-for&quot;&gt;More Than You Asked For&lt;/h2&gt;

&lt;p&gt;And finally, here’s a kitchen sink example. Have a look at the names
of these sources and play around with any that sound useful:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-source-findutils&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-recentf&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-bookmarks&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-buffers-list&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-google-suggest&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-locate&lt;/span&gt;
                   &lt;span class=&quot;nv&quot;&gt;helm-source-ls-git&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*helm all the things*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And if that’s not enough, with helm enabled, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h v helm-source&lt;/code&gt; will
give you even more to digest…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Set An OSX Window To A Specific Size</title>
		  <pubDate>Mon, 07 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/set-an-osx-window-to-a-specific-size.html</link>
		  <guid>http://blog.jenkster.com/2013/10/set-an-osx-window-to-a-specific-size.html</guid>
		  <description>&lt;p&gt;This is a handy tip: I wanted to set a terminal window to a specific
size, to check it was going to work on a projector later. This command
line does the trick:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;osascript &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'tell application &quot;terminal&quot; to set the bounds of the first window to {0, 0, 1280, 720}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{left, top, right, bottom}&lt;/code&gt;.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>A Tip For Navigating Clojure Files in Emacs</title>
		  <pubDate>Wed, 02 Oct 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/10/a-tip-for-navigating-clojure-files-in-emacs.html</link>
		  <guid>http://blog.jenkster.com/2013/10/a-tip-for-navigating-clojure-files-in-emacs.html</guid>
		  <description>&lt;p&gt;Here’s a little Emacs trick I’ve starting using recently for
navigating Clojure. It’s an easy way to get a map of the file you’re
working on, and jump around it. Once it’s working, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/helm-headlines.png&quot; alt=&quot;Helm Clojure Headlines&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To set it up, first you’ll need &lt;a href=&quot;https://github.com/emacs-helm/helm&quot;&gt;helm&lt;/a&gt;, so if you don’t have it
installed call:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  M-x package-install
  helm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, stick this in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.emacs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;helm-clojure-headlines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Display headlines for the current Clojure file.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Clojure Headlines&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;volatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;headline&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;^[;(]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Eval it, and you’re away. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x helm-clojure-headlines&lt;/code&gt; will bring up the
map. You can type a string to narrow down the list. Hitting return
will leap to that point in the file. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-p&lt;/code&gt; will move through the
list of matches.&lt;/p&gt;

&lt;p&gt;How does it work? Mostly through Helm magic. All you really need to
think about is the:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;headline&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;^[;(]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…part. That’s just a regular expression that tells helm which lines
in the file are headlines. For Clojure, I like “starts with a
semicolon or opening parenthesis”.&lt;/p&gt;

&lt;p&gt;For a more involved example, I use this version for Objective-C:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;helm-objc-headlines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Objective-C Headlines&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;volatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;headline&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;&quot;^[-+@]\\|^#pragma mark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A trickier regex, but still a very easy thing to setup for all it
supplies. And this trick works for any filetype you can think of a
sensible pattern to match against.&lt;/p&gt;

&lt;p&gt;Give it a whirl. If you like it, I leave it to you to bind your own
shortcut key. Oh, and you might like another, more complex thing I
built with helm: &lt;a href=&quot;https://github.com/krisajenkins/clojure-cheatsheet&quot;&gt;The Clojure Cheatsheet for Emacs&lt;/a&gt;. :-)&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Chicken, Chicken, Chicken</title>
		  <pubDate>Tue, 27 Aug 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/08/chicken-chicken-chicken.html</link>
		  <guid>http://blog.jenkster.com/2013/08/chicken-chicken-chicken.html</guid>
		  <description>&lt;h2 id=&quot;chicken&quot;&gt;Chicken:&lt;/h2&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clojure.walk&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clojure.pprint&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clojure.string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;walk/postwalk&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cond&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                                           &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\w+&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                                           &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;chicken&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;symbol?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;'chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                      &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                   &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chicken-chicken&quot;&gt;Chicken chicken:&lt;/h2&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alter-map-values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Given a map, derive a new one where all the keys are passed through f.
      If f returns nil, the key is unchanged.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;altered&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;altered&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
		 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	     &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chicken-chicken-chicken&quot;&gt;Chicken, Chicken, Chicken:&lt;/h2&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;chicken chicken chicken, chicken chicken chicken chicken chicken chicken chicken chicken chicken chicken chicken chicken.
  chicken chicken chicken chicken, chicken chicken chicken chicken.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chicken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chickens&quot;&gt;Chickens:&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=yL_-1d9OSdk&quot;&gt;Chicken&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.fogus.me/2013/07/17/an-introduction-to-deep-code-walking-macros-with-clojure/&quot;&gt;Chicken Chicken&lt;/a&gt;&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>West London Hack Night - August 2013</title>
		  <pubDate>Fri, 16 Aug 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/08/west-london-hack-night-august-2013.html</link>
		  <guid>http://blog.jenkster.com/2013/08/west-london-hack-night-august-2013.html</guid>
		  <description>&lt;p&gt;Anonther &lt;a href=&quot;http://www.meetup.com/West-London-Hack-Night/events/130356642/&quot;&gt;West London Hack Night&lt;/a&gt;, and another success I’d say. We
picked a tough one this time: Write an interpreter and a virtual
machine in 90 minutes. That challenge was made both easier and harder
by the choice of language: &lt;a href=&quot;http://en.wikipedia.org/wiki/Brainfuck&quot;&gt;Brainfuck&lt;/a&gt;. It’s got a very simple
specification, but the language is so hard to read that debugging the
interpreter becomes a real brain…ache.&lt;/p&gt;

&lt;p&gt;By my count we mustered 20 people spread across 7 teams. Not everyone
managed to finish, but here are the projects that got published:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/denchev/brainfuck-php&quot;&gt;PHP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/Roysvork/6251663&quot;&gt;C#&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/dpdawson/ruby-brainfuck&quot;&gt;Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/funkotron/brainfuck&quot;&gt;Clojure&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/adamretter/Skullfuck&quot;&gt;Scala&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pljones/brain/blob/master/brainfuck.html&quot;&gt;JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not a bad result at all - almost everyone went home able to say they’d
implemented a Turing Complete programming language from scratch…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>The Turing Rule</title>
		  <pubDate>Tue, 06 Aug 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/08/the-turing-rule.html</link>
		  <guid>http://blog.jenkster.com/2013/08/the-turing-rule.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;If someone tries to end a debate about programming languages by
invoking Turing Equivalence, you are allowed to give them a long reel
of tape and steal their laptop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If mathematical equivalence were the only thing that mattered in
language design, we’d all be using Turing tape. Turing Equivalence is
what qualifies a language to enter the debate, not what finishes it.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Designing An Accounting System</title>
		  <pubDate>Tue, 06 Aug 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/08/designing-an-accounting-system.html</link>
		  <guid>http://blog.jenkster.com/2013/08/designing-an-accounting-system.html</guid>
		  <description>&lt;p&gt;A fast thought on writing accounting software: The most common mistake
programmers make when writing an accounting system is they think it’s
all about balances. They think the point of an accounting system is to
tell you your account balance, so they design the data model around
that.&lt;/p&gt;

&lt;p&gt;They’re wrong. The point of an accounting system is to track the
complete history of the movements of money and other assets. Auditing
isn’t just a feature of the system, &lt;em&gt;it is the system&lt;/em&gt;. Balances are
just a summary report on the &lt;em&gt;real&lt;/em&gt; data.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Quote of the Day</title>
		  <pubDate>Thu, 18 Jul 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/07/quote-of-the-day.html</link>
		  <guid>http://blog.jenkster.com/2013/07/quote-of-the-day.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;Programmers talk about software development on weekends, vacations,
and over meals not because they lack imagination, but because their
imagination reveals worlds that others cannot see. - &lt;a href=&quot;https://en.wikiquote.org/wiki/Programming&quot;&gt;Thinking in C#&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</description>
		</item>
    
		<item>
		  <title>West London Hack Night - July 2013</title>
		  <pubDate>Sat, 13 Jul 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/07/west-london-hack-night-july-2013.html</link>
		  <guid>http://blog.jenkster.com/2013/07/west-london-hack-night-july-2013.html</guid>
		  <description>&lt;p&gt;&lt;a href=&quot;http://www.meetup.com/West-London-Hack-Night/events/120495682/][Last Thursday's]] [[http://www.meetup.com/West-London-Hack-Night/&quot;&gt;West London Hack Night&lt;/a&gt; was great fun. The chosen topic
was Genetic Algorithms. More specifically, given a pool of random
strings, can you use GA to get them to evolve towards a target?&lt;/p&gt;

&lt;p&gt;It’s a simple application of a sophisticated idea, but perhaps a
perfect way to get started as you actually can code it up in about an
hour and a half.&lt;/p&gt;

&lt;p&gt;There were four teams hacking in four different languages, and here’s
their code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/krisajenkins/javascriptgeneticalgorithm&quot;&gt;JavaScript&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/oppianmatt/westlondonhack_20130711&quot;&gt;Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/t-ob/genetic&quot;&gt;Clojure&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/CaffeinatedDave/GeneticAlgorithms&quot;&gt;Scala&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great fun, as usual. I’m already looking forward to the next.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Levenshtein Distance in Elisp</title>
		  <pubDate>Sun, 30 Jun 2013 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2013/06/levenshtein-distance-in-elisp.html</link>
		  <guid>http://blog.jenkster.com/2013/06/levenshtein-distance-in-elisp.html</guid>
		  <description>&lt;p&gt;Here’s a quick implementation of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Levenshtein_distance&quot;&gt;Levenshtein distance&lt;/a&gt; - a measure
of the similiarity of two strings - in Emacs Lisp.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;substring&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;substring&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cond&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-equal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
                       &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sunday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Saturday&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Saturday&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sunday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sitting&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;kitten&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levenshtein&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sitting&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;kittin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: I wrote this for interest’s sake, because I couldn’t sleep. If
you need a real implementation, you’d probably be better off with &lt;a href=&quot;http://www.emacswiki.org/emacs/levenshtein.el&quot;&gt;the one from EmacsWiki&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Solving Logic Puzzles With Clojure's Core Logic, Part One</title>
		  <pubDate>Wed, 27 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/solving-logic-puzzles-with-clojures-corelogic.html</link>
		  <guid>http://blog.jenkster.com/2013/02/solving-logic-puzzles-with-clojures-corelogic.html</guid>
		  <description>&lt;p&gt;I used to love solving logic puzzles as a kid. Bought books of
‘em. Great fun. They’re a puzzle with this sort of shape:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;There are four sets of five things. For example, 5 people, 5
magazines, 5 reservation times and 5 cheeses.&lt;/li&gt;
  &lt;li&gt;There are rules that connect them together, like, “Jason likes mozzarella.”&lt;/li&gt;
  &lt;li&gt;The rules are exclusive. If we’re told Jason likes mozzarella, then
Jason likes no other cheese, and nobody else likes mozzarella.&lt;/li&gt;
  &lt;li&gt;You are given enough clues about the relationships between these
things that only one possible configuration can exist.  Find it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It cries out, “Logic Programming”, doesn’t it? Well, recently the
London Cloure group took a crack at it. We got pretty far, but didn’t
complete it before the night was over. I thought I’d finish it off and
write it up, for your pleasure. Here goes…&lt;/p&gt;

&lt;p&gt;I’ve taken a puzzle from &lt;a href=&quot;http://www.logic-puzzles.org/init.php&quot;&gt;Logic Puzzles.org&lt;/a&gt;, who seem to have a army of
them. Here are the sets of things we’re dealing with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;People&lt;/em&gt;: Amaya, Bailey, Jamari, Jason &amp;amp; Landon.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Cheeses&lt;/em&gt;: Asiago, Blue Cheese, Mascarpone, Mozzarella &amp;amp; Muenster&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Magazines&lt;/em&gt;: Fortune, Time, Cosmopolitan, US Weekly &amp;amp; Vogue&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Reservation times&lt;/em&gt;: 5pm, 6pm, 7pm, 7:30pm, 8:30pm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here are the rules. You can skim over them. We’ll go through them
in detail in &lt;a href=&quot;post:2013-02-27-solving-logic-puzzles-with-clojures-core-logic-part-two&quot;&gt;part two&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;Of Landon and Jason, one has the 7:30pm reservation and the other loves mozzarella.&lt;/li&gt;
    &lt;li&gt;The blue cheese enthusiast subscribed to Fortune.&lt;/li&gt;
    &lt;li&gt;The muenster enthusiast didn’t subscribe to Vogue.&lt;/li&gt;
    &lt;li&gt;The 5 people were the Fortune subscriber, Landon, the person with a
reservation at 5:00pm, the mascarpone enthusiast, and the Vogue
subscriber.&lt;/li&gt;
    &lt;li&gt;The person with a reservation at 5:00pm didn’t subscribe to Time.&lt;/li&gt;
    &lt;li&gt;The Cosmopolitan subscriber has an earlier reservation than the mascarpone enthusiast.&lt;/li&gt;
    &lt;li&gt;Bailey has a later reservation than the blue cheese enthusiast.&lt;/li&gt;
    &lt;li&gt;Either the person with a reservation at 7:00pm or the person with a
reservation at 7:30pm subscribed to Fortune.&lt;/li&gt;
    &lt;li&gt;Landon has a later reservation than the Time subscriber.&lt;/li&gt;
    &lt;li&gt;The Fortune subscriber is not Jamari.&lt;/li&gt;
    &lt;li&gt;The person with a reservation at 5:00pm loves mozzarella.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s only one possible solution, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt; is going to find it for us.&lt;/p&gt;

&lt;h2 id=&quot;before-we-start-whats-an-lvar&quot;&gt;Before We Start, What’s An &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvar&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;Imagine a closed box. I’ll tell you that inside the box is
something that is grey, weighs one tonne, and has a horn on its
nose. When we open the box, you won’t be surprised to see it
contains a rhino. That’s how I think of a logic variable, or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvar&lt;/code&gt;. It’s a box containing something that’s unknown right
now. We can state some rules about what must be inside, and when we
come to open the box, the right kind of thing will pop out.&lt;/p&gt;

&lt;p&gt;So, with that in mind, let’s set up our solution.&lt;/p&gt;

&lt;h2 id=&quot;the-setup&quot;&gt;The Setup&lt;/h2&gt;

&lt;p&gt;We’ll start with this code:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we’ve done four things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Called the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvar&lt;/code&gt; function five times, to create boxes for the five people.&lt;/li&gt;
  &lt;li&gt;Repeated that three more times for magazines, cheeses and
reservations.&lt;/li&gt;
  &lt;li&gt;Spliced those four lists together, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(map list ...)&lt;/code&gt;, to
create a structure that’s a list of five &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[person, magazine, cheese,
reservation-time]&lt;/code&gt; tuples. When we open all those boxes, we’ll have
our answer.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt; a simple query: “Find all the qs, such that q is a possible answer.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far, so good. Now all we need to do is add the right
constraints, and the boxes will magically open to reveal the single
answer to the puzzle.&lt;/p&gt;

&lt;h2 id=&quot;first-constraints&quot;&gt;First Constraints&lt;/h2&gt;

&lt;p&gt;So the first thing we need to constrain is the list of people,
magazines, cheeses and reservations. This would be a start:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:amaya&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:bailey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jamari&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jason&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:cosmopolitan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:us-weekly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:asiago&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That says that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;people&lt;/code&gt; matches the list of five names, but not
necessarily in the same order. It’s a permutation of the given
list. We repeat that pattern for all four kinds of thing.&lt;/p&gt;

&lt;p&gt;That’s almost right, but there’s a problem with ordering. Even once
we’ve figured out the correct tuples, we’re going to get them in
all possible orders, which is 5! or 120 answers, all of which are
equivalent.&lt;/p&gt;

&lt;p&gt;There are a few ways to handle this. We could to use a Set for the
answers, instead of a list. That would be good in theory, but
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt; doesn’t support sets&lt;sup id=&quot;fnref:yet&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:yet&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. We could ignore the
problem and just take whichever answer pops out first. Or we could
define a fixed order for any &lt;em&gt;one&lt;/em&gt; of the collections, and let the
others fall in line with that.&lt;/p&gt;

&lt;p&gt;Fixing the order is the approach I like, because then there’s only
one possible solution, which makes it easy to check we’ve got the
rest of the code right later. So let’s fix the order of the people:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:amaya&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:bailey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jamari&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jason&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:cosmopolitan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:us-weekly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:asiago&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And with that, we’re ready to start encoding puzzle rules. We’ll
   pull them out as separate functions, so our final main function
   will look like this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:amaya&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:bailey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jamari&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jason&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-9&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rule-11&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:cosmopolitan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:us-weekly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cheeses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:asiago&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservations&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll look at the individual rules in &lt;a href=&quot;post:2013-02-27-solving-logic-puzzles-with-clojures-core-logic-part-two&quot;&gt;part two…&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:yet&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Yet. &lt;a href=&quot;#fnref:yet&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Solving Logic Puzzles With Clojure's Core Logic, Part Two</title>
		  <pubDate>Wed, 27 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/solving-logic-puzzles-with-clojures-core-logic-part-two.html</link>
		  <guid>http://blog.jenkster.com/2013/02/solving-logic-puzzles-with-clojures-core-logic-part-two.html</guid>
		  <description>&lt;p&gt;&lt;a href=&quot;/2013/02/solving-logic-puzzles-with-clojures-corelogic.html&quot;&gt;In part one&lt;/a&gt; we laid the foundations for solving logic puzzles with
Clojure and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt;. We built a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt; query that encodes&lt;/p&gt;

&lt;p&gt;rules of this particular puzzle, and come up with a solution.&lt;/p&gt;

&lt;h1 id=&quot;the-rules&quot;&gt;The Rules&lt;/h1&gt;

&lt;p&gt;Let’s recap the rules:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;Of Landon and Jason, one has the 7:30pm reservation and the other loves mozzarella.&lt;/li&gt;
    &lt;li&gt;The blue cheese enthusiast subscribed to Fortune.&lt;/li&gt;
    &lt;li&gt;The muenster enthusiast didn’t subscribe to Vogue.&lt;/li&gt;
    &lt;li&gt;The 5 people were the Fortune subscriber, Landon, the person with a
reservation at 5:00pm, the mascarpone enthusiast, and the Vogue
subscriber.&lt;/li&gt;
    &lt;li&gt;The person with a reservation at 5:00pm didn’t subscribe to Time.&lt;/li&gt;
    &lt;li&gt;The Cosmopolitan subscriber has an earlier reservation than the mascarpone enthusiast.&lt;/li&gt;
    &lt;li&gt;Bailey has a later reservation than the blue cheese enthusiast.&lt;/li&gt;
    &lt;li&gt;Either the person with a reservation at 7:00pm or the person with a
reservation at 7:30pm subscribed to Fortune.&lt;/li&gt;
    &lt;li&gt;Landon has a later reservation than the Time subscriber.&lt;/li&gt;
    &lt;li&gt;The Fortune subscriber is not Jamari.&lt;/li&gt;
    &lt;li&gt;The person with a reservation at 5:00pm loves mozzarella.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you look through them there are only really 5 &lt;em&gt;kinds&lt;/em&gt; of rule in
this puzzle, so we’ll group them and tackle them in order of
complexitye&lt;/p&gt;

&lt;h2 id=&quot;simple-facts&quot;&gt;Simple Facts&lt;/h2&gt;

&lt;p&gt;Rules (2) and (11) are the simplest:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* The blue cheese enthusiast subscribed to Fortune.
* The person with a reservation at 5:00pm loves mozzarella.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first we handle by saying, “one of the answers - and we don’t care
which one - has the shape &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[* :fortune :blue-cheese *]&lt;/code&gt;. We handle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;
with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(lvar)&lt;/code&gt;, and one-but-any-one with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;membero&lt;/code&gt;, to give us this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The blue cheese enthusiast subscribed to Fortune.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In English, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[* :fortune :blue-cheese *]&lt;/code&gt; is a member of the answer list.&lt;/p&gt;

&lt;p&gt;That’s fine, but I’ve a feeling we’re going to be writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(lvar)&lt;/code&gt; a
lot, so for rule 11 we’ll start using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clojure.tools.macro/symbol-macrolet&lt;/code&gt; for easier syntax:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-11&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The person with a reservation at 5:00pm loves mozzarella.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;negated-facts&quot;&gt;Negated Facts&lt;/h2&gt;

&lt;p&gt;The second class of rules are negations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The muenster enthusiast didn’t subscribe to Vogue.&lt;/li&gt;
  &lt;li&gt;The person with a reservation at 5:00pm didn’t subscribe to Time.&lt;/li&gt;
  &lt;li&gt;The Fortune subscriber is not Jamari.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we solve those, let’s take a look at a naive first-pass that tripped me up:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BAD-rule-3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The muenster enthusiast didn't subscribe to Vogue.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;not-membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-membero&lt;/code&gt; isn’t a built-in function of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt;, but &lt;a href=&quot;http://stackoverflow.com/questions/11964055/constraining-two-vectors-to-be-in-the-same-domain-but-not-be-members-of-each-ot&quot;&gt;it’s easy enough to find&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sadly this doesn’t work. It looks like it’s saying, “Match a person
who likes Vogue and muenster cheese and make sure it’s not in the list
of answers.” But really it’s saying, “Is it possible to construct a
tuple that has Vogue and muenster, but &lt;em&gt;isn’t&lt;/em&gt; in the answer list?”
That answer to that is, yes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[nil :vogue :muenster nil]&lt;/code&gt; would be
such a tuple. So the rule is trivially and always true. In effect, it
does nothing.&lt;/p&gt;

&lt;p&gt;No, to encode these rules correctly we need to say something about
what &lt;em&gt;is&lt;/em&gt; in the answer list, and then make extra assertions about
those things. We need to say, “There’s a tuple with Vogue, a tuple
with muenster, they’re both in the answer list but they aren’t the
same tuple.” Like this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The muenster enthusiast didn't subscribe to Vogue.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That works. And note the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fresh&lt;/code&gt; to introduce the named, local logic variables (magic boxes) we need.&lt;/p&gt;

&lt;p&gt;Let’s encode the other two rules of this type:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The person with a reservation at 5:00pm didn't subscribe to Time.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The Fortune subscriber is not Jamari.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jamari&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;related-pairs&quot;&gt;Related Pairs&lt;/h2&gt;

&lt;p&gt;The third class of rules relate pairs of facts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Either the person with a reservation at 7:00pm or the person with
a reservation at 7:30pm subscribed to Fortune.”&lt;/li&gt;
  &lt;li&gt;Of Landon and Jason, one has the 7:30pm reservation and the other loves mozzarella.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conde&lt;/code&gt; to make some OR statements. Here’s the code for the first rule:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Either the person with a reservation at 7:00pm or the person with a
   reservation at 7:30pm subscribed to Fortune.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conde&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is saying, “There’s an answer with Fortune in it, and I want to
make a further assertion about the reservation, so name it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;. My
further assertion is, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; is either 7pm or 7:30pm.”&lt;/p&gt;

&lt;p&gt;Fairly simple. And the next is only a little more complicated:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Of Landon and Jason, one has the 7:30pm reservation and the other loves mozzarella.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jason&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conde&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is saying, “There’s an answer with Landon in, and I want to make
some assertions about his choice of cheese &amp;amp; reservation. Ditto for
Jason&lt;sup id=&quot;fnref:json&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:json&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.”  Then the assertions, “Either the first reservation
is 7:30pm and the second cheese is mozarella, or the other way
around.”&lt;/p&gt;

&lt;h2 id=&quot;mutual-exclusion&quot;&gt;Mutual Exclusion&lt;/h2&gt;

&lt;p&gt;Now we’re on to the home straight. The next class of rules - actually
there’s only one of them - is a description of five separate tuples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The 5 people were the Fortune subscriber, Landon, the person with
a reservation at 5:00pm, the mascarpone enthusiast, and the Vogue
subscriber.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing to notice here is that the rule’s really saying, whoever has
one trait in that list can’t have any of the others. So we can use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permuteo&lt;/code&gt; again to describe all 5 tuples, allowing for the facts to
appear in any order:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The 5 people were the Fortune subscriber, Landon, the person with a
   reservation at 5:00pm, the mascarpone enthusiast, and the Vogue
   subscriber.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permuteo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;relative-facts&quot;&gt;Relative Facts&lt;/h2&gt;

&lt;p&gt;Okay, last class of rule:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The Cosmopolitan subscriber has an earlier reservation than the mascarpone enthusiast.&lt;/li&gt;
  &lt;li&gt;Bailey has a later reservation than the blue cheese enthusiast.&lt;/li&gt;
  &lt;li&gt;Landon has a later reservation than the Time subscriber.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all very similar to the related pairs above, but with a
greater-than or less-than statement that makes things a little
tricker. Actually, it makes things much trickier, as we can’t just use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.logic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I’ve taken an easy way out here. If I say that the reservation times
are in strict order &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[5 6 7 7.5 8.5]&lt;/code&gt;, then I can make greater-than
and less-than statements by saying one is to the left of another.&lt;/p&gt;

&lt;p&gt;I’ll define to-the-left-of as this:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defne&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lefto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x appears to the left of y in collection l.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lefto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In English, “either x is the head of the list and y is a member of its
tail OR drop the head and recur.”&lt;/p&gt;

&lt;p&gt;With that helper in place, the next three rules should look pretty clear:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The Cosmopolitan subscriber has an earlier reservation than the
   mascarpone enthusiast.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:cosmopolitan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lefto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bailey has a later reservation than the blue cheese enthusiast.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:bailey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lefto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rule-9&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Landon has a later reservation than the Time subscriber.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;symbol-macrolet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fresh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;membero&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;answers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lefto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;take-it-home&quot;&gt;Take It Home&lt;/h1&gt;

&lt;p&gt;That’s it. Our driver function and our rules are all encoded. Running
it produces a list containing a single answer:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:amaya&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:fortune&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:blue-cheese&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:bailey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:vogue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:asiago&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jamari&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mascarpone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:jason&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:cosmopolitan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:mozzarella&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:landon&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:us-weekly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:muenster&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On my machine it takes about 1s to find the first answer, and about
16s to search exhaustively (and thus demonstrate that one answer is
all there is).&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;https://github.com/krisajenkins/LogicPuzzles&quot;&gt;find the code on GitHub&lt;/a&gt; if you want to give it a whirl.&lt;/p&gt;

&lt;p&gt;Thoughts? Questions? Suggestions? Leave a comment below…&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:json&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;One of the hard parts of writing this code was typing Jason instead of JSON. &lt;a href=&quot;#fnref:json&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Writing Great Literature With Clojure</title>
		  <pubDate>Mon, 25 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/writing-great-literature-with-clojure.html</link>
		  <guid>http://blog.jenkster.com/2013/02/writing-great-literature-with-clojure.html</guid>
		  <description>&lt;p&gt;Witness the might of lazy evaluation:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;library.reference-section&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complete-works-of-shakespeare&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reference/complete-works-of-shakespeare&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;typing&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;monkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thanks to lazy evaluation, an infinite number of monkeys can
be easily evaluated, even in memory-constrained environments&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This technique can be used for any body of text for which you already have a reference copy. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Prolog Quote of the Day</title>
		  <pubDate>Fri, 22 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/prolog-quote-of-the-day.html</link>
		  <guid>http://blog.jenkster.com/2013/02/prolog-quote-of-the-day.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;Prolog is a great language for writing append; after that it’s all downhill.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;http://www.paulgraham.com/arcchallenge.html&quot;&gt;Paul Graham&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m not saying I agree or disagree, but it’s a good line…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Org Babel, Clojure and nREPL</title>
		  <pubDate>Thu, 21 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/org-babel-clojure-and-nrepl.html</link>
		  <guid>http://blog.jenkster.com/2013/02/org-babel-clojure-and-nrepl.html</guid>
		  <description>&lt;p&gt;At the moment, org-babel’s Clojure evaluator assumes you’re running
swank. But if you’ve made the switch from swank to nREPL, that’s not
going to work.  I bumped up against this problem this afternoon while
writing &lt;a href=&quot;/2013/02/deepest-node-in-a-binary-tree.html&quot;&gt;this little Clojure-related blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Getting org-babel to use nREPL is easy enough though. I’ve just added this to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.emacs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;eval-after-load&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ob-clojure&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-babel-execute:clojure&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;&quot;Execute a block of Clojure code with Babel and nREPL.&quot;&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'nrepl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nrepl-current-connection-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nrepl-eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-babel-expand-body:clojure&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read-from-string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;nREPL not connected!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s just a first pass. It works, but I’m not sure I’m handling all the
options correctly, so I’ll let it sit here for a while until I’ve
given it enough exercise to be worth submitting back to the main
project. Still, you might find it useful. Any feedback would be appreciated. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:-)&lt;/code&gt;&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>A Vim Front-End for gDocs</title>
		  <pubDate>Wed, 20 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/vim-google-docs.html</link>
		  <guid>http://blog.jenkster.com/2013/02/vim-google-docs.html</guid>
		  <description>&lt;p&gt;&lt;em&gt;tl;dr&lt;/em&gt; &lt;em&gt;Google Docs + Vim = Yay.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ah, the grail. Vim &lt;em&gt;everywhere&lt;/em&gt;. Once Vim’s got its claws in you, you
can’t settle for anything else. Every other editor is frustrating
and second-class.&lt;/p&gt;

&lt;p&gt;But for for Google Docs I’m forced to make an exception. It’s my ideal
way to work with normal people&lt;sup id=&quot;fnref:geek&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:geek&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Especially when it’s
changing a lot.  Google Docs is user-friendly, it’s got all the
features we need, and no-one ever stops the conference call to say,
“Wait - did I email you the latest version?”&lt;/p&gt;

&lt;p&gt;But I still don’t want to give up Vim. How could we connect the two?
The way I see it, there are three possible solutions.&lt;/p&gt;

&lt;h2 id=&quot;vim-talks-to-google&quot;&gt;Vim talks to Google.&lt;/h2&gt;

&lt;p&gt;We could build a plugin for Vim that connects to the Google Docs
server. Ever since &lt;a href=&quot;http://googlewave.blogspot.co.uk/&quot;&gt;Google Wave&lt;/a&gt; came &amp;amp; went, there has been plenty of
information available on how to build a collaborative document-editing
system. We can assume that Google Docs approaches the problem along
these lines. The problem I think, wouldn’t be with the
protocol, but with Vim itself.&lt;/p&gt;

&lt;p&gt;Vim is single-threaded, so it’s not going to lend itself well to
listening asynchronously for changes from the central server. We could
probably work around that by reaching out from Vim into Python or
Ruby, but that instantly puts us into the realms of, “If this plugin
doesn’t work, simply re-compile your copy of Vim.” Yuck.&lt;/p&gt;

&lt;p&gt;Also, Vim has a strictly text-only display. Even if we could happily
listen for changes, displaying them is going to be tricky. We could
use some syntax-highlighting tricks to simulate multiple cursors, but
I think it’s always going to look like a hack.&lt;/p&gt;

&lt;p&gt;I don’t think building Google Docs collaborative editing into Vim is
impossible&lt;sup id=&quot;fnref:existing&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:existing&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, but I’m certain it would be swimming against the
tide. Getting it to work &lt;em&gt;well&lt;/em&gt; would be a mammoth project.&lt;/p&gt;

&lt;h2 id=&quot;maybe-emacs&quot;&gt;Maybe Emacs?&lt;/h2&gt;

&lt;p&gt;Emacs has a very good Vim-emulation mode, and copes well will multiple
processes and displaying text-with-extras&lt;sup id=&quot;fnref:multiple&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:multiple&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. It would be
possible. In fact, I’ve built a prototype myself, and whilst it’s not
releasable, it certainly proves the concept. But it puts us in an even
worse position: “To install this plugin, just install &lt;em&gt;Emacs&lt;/em&gt;.”  I
can’t see any Vim user accepting that as a solution&lt;sup id=&quot;fnref:emacs&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:emacs&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;that would give some clues.&lt;/p&gt;

&lt;h2 id=&quot;some-other-collaboration-service&quot;&gt;Some other collaboration service.&lt;/h2&gt;

&lt;p&gt;Another way forward would be to bypass both Vim &amp;amp; Google Docs for
something Vim-like and Google Docs-like, that’s better suited to the
task. There are a few online editors that offer collaboration, and
several of them are based on &lt;a href=&quot;http://codemirror.net/&quot;&gt;CodeMirror&lt;/a&gt;&lt;sup id=&quot;fnref:codemirror&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:codemirror&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, which has a passable
Vi-emulation mode.&lt;/p&gt;

&lt;p&gt;This is probably the shortest path to a solution, but it still suffers
from our opening problem: You have to turn to your non-technical
colleagues and say, “Can we switch from Google Docs just so I can use
Vim?”, and they look at you like you’re an alien. No, the right
solution won’t involve having to change an existing team’s behaviour
just to accommodate our preferences.&lt;/p&gt;

&lt;h2 id=&quot;google-docs-becomes-vim-like&quot;&gt;Google Docs becomes Vim-like.&lt;/h2&gt;

&lt;p&gt;So the last solution, and I think the only viable one, is to graft a
Vim-like input system on top of Google Docs. If we do that, we don’t
have to disturb existing users, we ought to get live collaboration &amp;amp;
display for free, and we just have to worry about one key problem: How
much Vim do we need? How much would we have to implement before we
felt at home in Google Docs?&lt;/p&gt;

&lt;p&gt;Naive Vim extensions rarely seem to get much beyond &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESC, h, j, k, l&lt;/code&gt;
before they think they’ve got the essence of Vim.  We know there’s
much more to it. With that in mind, here’s my list of what we’d need,
and a few things I think we can leave out:&lt;/p&gt;

&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Vim-like editing for Google Documents, without disturbing ordinary users.&lt;/li&gt;
  &lt;li&gt;Support for:
    &lt;ul&gt;
      &lt;li&gt;Modal editing. (Normal, insert and visual modes).&lt;/li&gt;
      &lt;li&gt;First-class motions &amp;amp; text objects. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d5j&lt;/code&gt; should delete 5 lines. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ci(&lt;/code&gt; should
change all the text in the current parentheses.&lt;/li&gt;
      &lt;li&gt;Ex commands. Not a direct translation of the Vim ones, but
something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:wordcount&lt;/code&gt; should trigger the word-count
box. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help&lt;/code&gt; should trigger the Google Docs help.&lt;/li&gt;
      &lt;li&gt;Custom keyboard mappings. Some equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nnoremap&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Windowing commands remapped to switch between main, comment and sharing panes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;non-requirements&quot;&gt;Non-requirements&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Plugins. Not for v1 at least.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I think it would be the right approach. I think it would be a
reasonably-sized project. I think it would make the world a better
place. So I’m putting the idea out into the world. What do you think?&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:geek&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Normal people. Non-geeks. People whom, I accept, shouldn’t be expected to learn Vim. &lt;a href=&quot;#fnref:geek&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:existing&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I should note that &lt;a href=&quot;http://blog.milford.io/2010/06/sweet-use-vim-with-google-docs/&quot;&gt;it’s possible to edit Google Documents with Vim&lt;/a&gt; using the &lt;a href=&quot;http://code.google.com/p/googlecl/&quot;&gt;Google Command Line&lt;/a&gt; tool. But that approach struggles with translating between gDocs’ format and plain text, and it doesn’t work collaboratively at all. &lt;a href=&quot;#fnref:existing&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:multiple&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/magnars][Magnar Sveen]] of [[http://emacsrocks.com/][Emacs Rocks]] has a nice [[https://github.com/magnars/multiple-cursors.el&quot;&gt;multiple cursors&lt;/a&gt; project &lt;a href=&quot;#fnref:multiple&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:emacs&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;post:2013-02-16-mapping-jk-in-emacs-evil-mode&quot;&gt;As I’ve written&lt;/a&gt;, these days Emacs is one of my favourite versions of Vim. But I don’t expect to convert anyone. (Hell, I’m not even certain I’d want to.) But if you like Vim &amp;amp; Lisp, it’s worth taking a look at &lt;a href=&quot;http://gitorious.org/evil/pages/Home&quot;&gt;Evil-mode&lt;/a&gt;. &lt;a href=&quot;#fnref:emacs&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:codemirror&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;CodeMirror’s Vim-mode is far from perfect, but it wouldn’t be hard to make it much, much better. And the same thing goes for all the browser-based Vim emulations: Not good enough, but a good start. &lt;a href=&quot;#fnref:codemirror&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Deepest Node In A Binary Tree</title>
		  <pubDate>Wed, 20 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/deepest-node-in-a-binary-tree.html</link>
		  <guid>http://blog.jenkster.com/2013/02/deepest-node-in-a-binary-tree.html</guid>
		  <description>&lt;p&gt;Since a friend has just raised the question, “Find the deepest node in
a binary tree,” here’s my Clojure-flavoured answer:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leaf?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deepest&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;leaf?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leaf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deepest&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:left&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                                      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deepest&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:right&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]))]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leaf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here it is in action:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deepest&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:left&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:right&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:left&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:left&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                         &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:right&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:right&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;| 3 | C |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;His response? “It’s &lt;em&gt;a bit&lt;/em&gt; longer in C++.”&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Mapping &quot;jk&quot; to Escape in Emacs' evil-mode</title>
		  <pubDate>Sat, 16 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/mapping-jk-in-emacs-evil-mode.html</link>
		  <guid>http://blog.jenkster.com/2013/02/mapping-jk-in-emacs-evil-mode.html</guid>
		  <description>&lt;p&gt;I’m a Vim user. But more &amp;amp; more these days I find that one of my
favourite versions of Vim is Emacs. Specifically, its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evil-mode&lt;/code&gt;
package, which is a very good Vim emulator&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;If you get started with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evil-mode&lt;/code&gt;, one of the first questions you
might ask is, “How do I remap ESC to something more finger-friendly?”
Some people like to map &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jj&lt;/code&gt;. Personally I like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jk&lt;/code&gt;, because it rolls
off the fingers a little more easily.&lt;/p&gt;

&lt;p&gt;Anyway, there are a couple of ways to do it in Emacs. The simplest &amp;amp;
cleanest I’ve found is to install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key-chord&lt;/code&gt; package:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package-install&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;key-chord&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…then add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.emacs&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'key-chord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key-chord-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key-chord-define&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;evil-insert-state-map&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;&quot;jk&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-normal-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Easy.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Actually, it’s the &lt;em&gt;only&lt;/em&gt; good Vim emulator/plugin I’ve ever encountered. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>.emacs, To Start With</title>
		  <pubDate>Sat, 16 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/emacs-to-start-with.html</link>
		  <guid>http://blog.jenkster.com/2013/02/emacs-to-start-with.html</guid>
		  <description>&lt;p&gt;This isn’t an original recipe, but this is how I kick off my .emacs
settings to ensure that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-packages&lt;/code&gt; are auto-installed.&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Package magic.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'package-archives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;melpa&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://melpa.milkbox.net/packages/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-packages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;evil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;key-chord&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elscreen&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ace-jump-mode&lt;/span&gt;
                           &lt;span class=&quot;nv&quot;&gt;surround&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;recentf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;magit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;A list of packages to check for and install at launch.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-missing-packages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;missing-packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dolist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-packages&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;missing-packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-installed-p&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;missing-packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;missing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-missing-packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;missing&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;;; Check for new packages (package versions)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-refresh-contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;;; Install the missing packages&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-installed-p&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-install&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>A Simple Data Equation</title>
		  <pubDate>Sat, 16 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/a-simple-data-equation.html</link>
		  <guid>http://blog.jenkster.com/2013/02/a-simple-data-equation.html</guid>
		  <description>&lt;p&gt;Take the number of copies you have of your data, and subtract
one. That’s how much your data matters to you.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Today I Learnt...Something About Stack Overflow</title>
		  <pubDate>Tue, 12 Feb 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/02/today_i_learnt.html</link>
		  <guid>http://blog.jenkster.com/2013/02/today_i_learnt.html</guid>
		  <description>&lt;p&gt;…that the way &lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;Stack Overflow&lt;/a&gt; detects
the syntax for a code-block is by looking at the tags on the
question. If your syntax-highlighting isn’t working, add the tag for
the language.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Clojure Syntax Highlighting in Emacs</title>
		  <pubDate>Sat, 26 Jan 2013 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2013/01/clojure-syntax-highlighting-in-emacs.html</link>
		  <guid>http://blog.jenkster.com/2013/01/clojure-syntax-highlighting-in-emacs.html</guid>
		  <description>&lt;p&gt;So you’ve just written a new macro for your Clojure DSL, and now you
have something like:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defwidget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my-widget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you’d love to add syntax highlighting to Emacs so that it gets
highlighted the way defn and defmacro do. Here are the magic words:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Adds new defn-esque keyword highlighting.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'clojure-mode-hook&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;font-lock-add-keywords&lt;/span&gt;
                &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(\\(defwidget\\)\\s-+\\(\\w+\\)&quot;&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;font-lock-keyword-face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;font-lock-function-name-face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What’s going on here? Well, let’s break it down:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Add a function that runs for any Clojure buffer.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'clojure-mode-hook&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; An anonymous function that takes no arguments.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;;; Set some new syntax-highlighting rules.&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;font-lock-add-keywords&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;;; So many escape codes! But we're really just saying:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Match the '(' character.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Match and group the string 'defwidget'.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Match some whitespace. \\s-+&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Match and group some word characters. \\w+&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(\\(defwidget\\)\\s-+\\(\\w+\\)&quot;&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;;; The first regexp group is a keyword.&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;font-lock-keyword-face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;;; The second regexp group is a name.&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;font-lock-function-name-face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; Close up the patient.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Lisp Quote of the Day</title>
		  <pubDate>Tue, 04 Dec 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/12/lisp_quote_of_the_day.html</link>
		  <guid>http://blog.jenkster.com/2012/12/lisp_quote_of_the_day.html</guid>
		  <description>&lt;blockquote&gt;
  &lt;p&gt;“Why are macros so important to Lisp programmers? Not merely for the
syntactic convenience they provide, but because they are programs that
manipulate programs, which has always been a central theme in the Lisp
community. If FORTRAN is the language that pushes numbers around, and
C is the language that pushes characters and pointers around, then
Lisp is the language that pushes programs around.”&lt;/p&gt;

  &lt;p&gt;Gabriel &amp;amp; Steele, The Evolution of Lisp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An old quote, but still thoroughly relevant. (Though today you’d
probably pick something in place of Fortran, and add a note about Java
being the language that pushes objects around.)&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Google Bootcamp Sarajevo</title>
		  <pubDate>Sun, 04 Nov 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/11/google_bootcamp_sarajevo.html</link>
		  <guid>http://blog.jenkster.com/2012/11/google_bootcamp_sarajevo.html</guid>
		  <description>&lt;p&gt;Two weeks ago, I was invited to fly to Sarajevo and run a Google
Bootcamp. We debated about the content for a bit, and settled on a
training &amp;amp; hacking day around &lt;a href=&quot;http://www.angularjs.org&quot;&gt;AngularJS&lt;/a&gt;. A couple of hour-long talks
from me, and as much hacking as possible. Cue frantic writing of
slides.&lt;/p&gt;

&lt;p&gt;On Friday we flew there via Vienna - not quite believing it was real -
and yesterday they came, they saw &amp;amp; they hacked:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/google-bootcamp-sarajevo.png&quot; alt=&quot;Presenting at Google Bootcamp&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It was a &lt;em&gt;fantastic&lt;/em&gt; day. Everyone had great fun &amp;amp; got their brains
filled with new ideas. Me too.&lt;/p&gt;

&lt;p&gt;I’m still churning over the event in my mind, it’s still buzzing my
brain, so I can’t really write an elegant post about it yet. But if
you’ll indulge, here are a few random memories while they’re fresh:&lt;/p&gt;

&lt;p&gt;The attendees were great. Apparently there’s not really a tech scene
in Sarajevo like there is in London. Talks like this are a rare
thing. But everyone was straight in and hacking. There were some
really great ideas being hacked on &amp;amp; everyone was keen to learn. Geeks
of Sarajevo, I salute you.&lt;/p&gt;

&lt;p&gt;Doug Crockford - I stole some of your JavaScript jokes. I’m
sorry. JavaScript jokes are hard to write and you cornered the market
early. To make up for it I told people to use JSLint &amp;amp; buy your book.&lt;/p&gt;

&lt;p&gt;I met the President! Well, I met a President. The event was held at a
university, and the current Arch-Chancellor is the ex-President of
Bosnia. He gives good handshake.&lt;/p&gt;

&lt;p&gt;At the start of the day, they clipped a microphone on me and said,
“Say something while we check the levels.” Normal people say, “One
two. One two.” I recited The Owl &amp;amp; The Pussy Cat. Parenthood has
changed me.&lt;/p&gt;

&lt;p&gt;One of the local TV stations showed up and interviewed me. That was
weird. On a day like this, hackers come up to you and ask things like,
“How do you conditionally hide DOM elements generated by an ng-repeat
tag?&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;” But TV people ask you questions like, “What do you think
this means for Bosnia?”  Under the circumstances, I think I switched
gear fairly smoothly. :-}&lt;/p&gt;

&lt;p&gt;As if we didn’t have enough to worry about, I decided that we’d
organize a couple of extra lightning talks. I figured on a day like
this it’s my job to throw as much information into people’s heads as I
possibly can. Amer - one of the guys helping me out - and I threw some
ideas onto a whiteboard, and people voted. Less and Hadoop won the
popular vote, so we each improvised 10 minutes of information. The
bonus talks seemed to go down really well. I’m glad we did it.  (For
the record, I did the Less talk. That’s easy. You pretty much just
have to say, “Less exists!” and people get it. Less rocks. Less is
easy and it rocks.)  (For the other record, I’d offered to do a Vim
Masterclass. It lost to Less by one vote. Sadface.)&lt;/p&gt;

&lt;p&gt;I love doing this kind of thing. It doesn’t matter if it’s a guitar or
a slideshow clicker in my hand, I like it. There’s a feeling that
comes upon you in the hours before the deadline. If you run away from
that feeling it’s called stagefright. If you run towards it it’s a
complete adrenaline rush. And speaking as a sedentary programmer who
hates sports, it’s rare that my body has reason to produce adrenaline.&lt;/p&gt;

&lt;p&gt;I wrote my own slideshow software. I’d normally scoff at such wheel
re-invention, but I really wanted to be able to show Angular working
live, within the slides, so I wrote an Angular slideshower that ran
Angular code inside my Angular slides&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.  But on the morning of
the event I hit a minor crisis. The room was unexpectedly huge, and
they handed me a wifi clicker. I’d expected to be standing near my
laptop and hadn’t written clicker support into the code. To my relief
&amp;amp; amazement, I managed to hack it in in about 5 minutes. Say what you
like about JavaScript, but I couldn’t have done that in Java or
Objective-C half as fast.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Answer: Don’t. Filter the ng-repeat values up-front instead. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;It’s rough - I might find some time and polish it up into a real app - but you can see it here if you like. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>LISP vs Java</title>
		  <pubDate>Thu, 01 Nov 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/11/lisp-vs-java.html</link>
		  <guid>http://blog.jenkster.com/2012/11/lisp-vs-java.html</guid>
		  <description>&lt;p&gt;This is &lt;a href=&quot;http://en.wikiquote.org/wiki/Lisp&quot;&gt;quote of the day&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;DOLIST is similar to Perl’s foreach or Python’s for. Java added a
similar kind of loop construct with the “enhanced” for loop in Java
1.5, as part of JSR-201. Notice what a difference macros make. A Lisp
programmer who notices a common pattern in their code can write a
macro to give themselves a source-level abstraction of that pattern. A
Java programmer who notices the same pattern has to convince Sun that
this particular abstraction is worth adding to the language. Then Sun
has to publish a JSR and convene an industry-wide “expert group” to
hash everything out. That process–according to Sun–takes an average
of 18 months. After that, the compiler writers all have to go upgrade
their compilers to support the new feature. And even once the Java
programmer’s favorite compiler supports the new version of Java, they
probably still can’t use the new feature until they’re allowed to
break source compatibility with older versions of Java. So an
annoyance that Common Lisp programmers can resolve for themselves
within five minutes plagues Java programmers for years.&lt;/p&gt;

  &lt;p&gt;Peter Seibel, Practical Common Lisp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So true. And that’s just for a language feature that everyone will
agree on. God help you if you want language feature in Java that’s
only useful to web developers.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>How To Make A Relational Database Schemaless</title>
		  <pubDate>Sat, 14 Jul 2012 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2012/07/how_to_make_a_relational_database_schemaless.html</link>
		  <guid>http://blog.jenkster.com/2012/07/how_to_make_a_relational_database_schemaless.html</guid>
		  <description>&lt;p&gt;Just in case this isn’t completely obvious:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_collection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;VARCHAR&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BLOB&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There you go - you can serialize any key-value pair you like, without
a schema. Heck, the values don’t even have to be of the same type.&lt;/p&gt;

&lt;p&gt;You may or may not want to do this, but you can. My point is, while
there are many good things to say about NoSQL databases,
schemalessness isn’t the interesting one. Enforcing a schema is a
feature. Not enforcing one is not.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Programmers, Your Text Editor Wasn't Designed For You</title>
		  <pubDate>Wed, 06 Jun 2012 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2012/06/programmers-your-text-editor-wasnt.html</link>
		  <guid>http://blog.jenkster.com/2012/06/programmers-your-text-editor-wasnt.html</guid>
		  <description>&lt;p&gt;As a programmer, the text editor is the core tool in your
world. Regardless of platform, language or environment, almost
everything you write will go through your editor of choice. And I’m
here to tell you folks: chances are, your text editor is the wrong
tool for the job. Here’s why….&lt;/p&gt;

&lt;p&gt;Most text editors are built to support a writer’s workflow. And a
writer’s workflow looks like this: Start a new document, append lots
of text, then later on, jump around a little &amp;amp; tweak:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/append-centric-editor.png&quot; alt=&quot;Append-Centric Editor&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The amount of jumping will vary depending on the writer, but the
workflow is essentially insert-centric. A tiny bit of time is spent
moving the cursor, the vast majority spent entering new text.&lt;/p&gt;

&lt;p&gt;And that’s the model that pretty much every text editor out there is
built on. Notepad &amp;amp; Word are built for writers, but so is the editor
in Eclipse, Xcode, IDEA &amp;amp; every other IDE I’ve ever seen. The workflow
is insert-centric, and any other features are just tacked onto a menu
at the top:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/fancy-insert-centric-editor.png&quot; alt=&quot;Fancy Insert-Centric Editor&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But we’re not writers! We’re programmers. Our workflow is completely
different. We spend very little time appending large chunks of new
text. We spend most of it jumping between functions, adding a bit
here, jumping there, deleting a few lines and moving them over to a
different file. We leap around, chopping, changing, expanding the code
all the day:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/manipulation-centric-editor.png&quot; alt=&quot;Manipulation-Centric Editor&quot; /&gt;&lt;/p&gt;

&lt;p&gt;No editor designed for writers will ever support a workflow like that
well. And (almost) every editor is either designed for writers, or an
extension of one that was. Adding more menu items to a fundamentally
wrong workflow doesn’t solve the problem. We need an editor that isn’t
insert-centric. We need one that’s manipulation-centric. An editor
that assumes very little of our time will be spent inserting en-masse,
and that most of it will be spent jumping around, tweaking, expanding
and refining. We need an editor that assumes multiple files at once is
the norm. We need an editor that makes changing five scattered
sentences at least as easy as entering one new paragraph. The writer’s
editor will not achieve this, no matter how many menu items it has.&lt;/p&gt;

&lt;p&gt;If your editor sends you to a mouse to select a paragraph, it’s not
good enough. If it expects you to edit one file at a time, it’s not
good enough. If jumping between two related functions in two separate
files requires a mouse, it’s not good enough. In short, if your editor
doesn’t make movement a first-class citizen, it’s not good enough.&lt;/p&gt;

&lt;p&gt;There is at least one solution to this problem. There is at least one
editor that’s designed, from the ground up, for a programmer’s
workflow. But I’m trying to avoid mentioning it, because this post
isn’t about converting people to my favourite editor. It’s about the
fact that most editors aren’t designed for us, and that we need a
solution.&lt;/p&gt;

&lt;p&gt;There are two and a half types of editor. Editors designed for
writers. Editors designed for writers, with dozens of functions tacked
onto the menu system. And editors actually designed for
programmers. Whichever one you pick, please make sure you’ve picked it
deliberately.&lt;/p&gt;

&lt;p&gt;PS: Okay, my chosen editor is Vim. It addresses a programmer’s
workflow beautifully. But this isn’t a pro-Vim rant. It’s a workflow
plea. You don’t have to pick my solution, but I hope you see the
problem &amp;amp; go looking for a solution.&lt;/p&gt;

&lt;p&gt;PPS: Some of my colleagues think I’m anti-IDE. I’m not. I just keep
coming back to the editor. Having an Integrated Development
Environment is nice. Integration is a lovely thing. But having an
editor designed for programming is essential. I’ll give up integration
for that, every time.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>A Handy Clojure Macro For Development vs. Production</title>
		  <pubDate>Sat, 31 Mar 2012 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2012/03/handy-clojure-macro-for-development-vs.html</link>
		  <guid>http://blog.jenkster.com/2012/03/handy-clojure-macro-for-development-vs.html</guid>
		  <description>&lt;p&gt;Here’s a quick little Clojure&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; macro I’ve started using.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.thebookfeed.com/&quot;&gt;The Book Feed&lt;/a&gt; is a new website I’ve put
together where you can write short book reviews, and optionally post
them to Facebook. When testing, I don’t want the post-to-Facebook code
to run while I’m developing, or my Facebook account would fill up with
test-data. It should really only run in production.&lt;/p&gt;

&lt;p&gt;That’s straightforward to code in any language. I write some kind of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isLive()&lt;/code&gt; function, then wrap the relevant code in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if ( isLive() ) {.... }&lt;/code&gt;. Easy, right?&lt;/p&gt;

&lt;p&gt;Well, in Clojure we can go one better. Take a look at this code:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is-live?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;if-live&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is-live?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DEVELOPMENT Skipping:&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…then later in my code I replace:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;post-to-facebook&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…with:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;if-live&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post-to-facebook&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At first glance this looks like syntactic sugar. It’s super-short, but
is it really any better than what we’d say in something like Java?&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isLive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;postToFacebook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DEVT Skipping: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, yes. This macro is significantly better, and not just because of
all the typing it saves. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-live&lt;/code&gt; macro has a magic property we’d
struggle to get in other languages: Instead of just skipping the code,
or printing a generic debugging message, it prints the exact code and
arguments it would execute were we in production. In other languages
we’re stuck with the tedious problem of keeping the log message &amp;amp; the
call in sync with each other&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;But because Clojure code can be treated as regular data, it’s trivial
to print the call instead of executing it. With no effort, I can see
exactly what the call would send to Facebook, without worrying about
keeping the debug message in sync with the function call.&lt;/p&gt;

&lt;p&gt;Yay macros.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Everything in this post is applicable to LISPs in general. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I can think of a few workarounds for a couple of languages, but nothing that comes close to the elegance of this macro. Nothing that says, “Add these 8 characters to any function and it just works.” &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>It's Complicated</title>
		  <pubDate>Tue, 20 Mar 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/03/its_complicated.html</link>
		  <guid>http://blog.jenkster.com/2012/03/its_complicated.html</guid>
		  <description>&lt;p&gt;This evening I saw a man who was incredibly buff. Take the fittest
I’ll ever be in my life, and he was far, far fitter at 60. He was so
toned he could easily have been a world-class yoga teacher. He wasn’t
a world-class yoga teacher. He was a world-class musician. He was
Sting.&lt;/p&gt;

&lt;p&gt;Sometimes I feel inadequate.&lt;/p&gt;

&lt;p&gt;I pray to God.&lt;/p&gt;

&lt;p&gt;I say, “God, sometimes I feel inadequate.”&lt;/p&gt;

&lt;p&gt;“That’s okay,” says God. “That’s why I created Tom Jones. He’s being
awesome enough for everyone.”&lt;/p&gt;

&lt;p&gt;He’s right.&lt;/p&gt;

&lt;p&gt;“Have a Gin &amp;amp; Tonic,” says God.&lt;/p&gt;

&lt;p&gt;He’s right again.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Letters to Juliet, A Film Review</title>
		  <pubDate>Mon, 05 Mar 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/03/letters-to-juliet-film-review.html</link>
		  <guid>http://blog.jenkster.com/2012/03/letters-to-juliet-film-review.html</guid>
		  <description>&lt;p&gt;Just in case you’re tempted to watch this film, let me save you the
bother and tell you what happens:&lt;/p&gt;

&lt;p&gt;Gael Garcia Bernal plays, ‘The only person in the film with an ounce
of charisma.’ He is engaged to a blonde personality vacuum with bad
dress sense. They fly to Verona. He runs off to do interesting things,
we are forced to stay in the hotel and watch her pout.&lt;/p&gt;

&lt;p&gt;After an hour of tedium, Ms Airhead finds the man she’s been looking
for. She is overjoyed. His soulless husk is as badly dressed as
hers. He is overjoyed too. He hasn’t had any real work since he left
Home &amp;amp; Away.&lt;/p&gt;

&lt;p&gt;Vanessa Regrave picks up a cheque, a free holiday in Italy, and a kiss
from Italy’s answer to Tom Jones. Given how little screen time is
given to septuagenarian nookie these days, she chalks the film up as a
personal victory.&lt;/p&gt;

&lt;p&gt;The End.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>How Do I Pick The Wrong Programming Language?</title>
		  <pubDate>Sun, 12 Feb 2012 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2012/02/how-do-i-pick-wrong-programming.html</link>
		  <guid>http://blog.jenkster.com/2012/02/how-do-i-pick-wrong-programming.html</guid>
		  <description>&lt;p&gt;A little thought experiment has been running around in my head for the
past couple of days. I thought I’d share it with you.&lt;/p&gt;

&lt;p&gt;It’s very hard to rank programming languages. We get a sense that some
are good &amp;amp; some are bad, but the more experience you have the more
caveats you have to allow: X is good (but it’s hard to find good X
programmers); Y is fairly bad (but it’s good for data-wrangling),
etc. Choosing the right language for the job is an art. But, as a
novel way of looking at the problem, here’s my thought experiment:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s a 5-year project coming up. You don’t know what it is. You
don’t know how many programmers will be working on it, or how good
they’ll be. You know nothing, except that it must be fairly large
because it’s a 5-year project.&lt;/p&gt;

  &lt;p&gt;You have one choice, and one objective. You get to choose the
programming language for the project. And your objective is to
guarantee that at the end of five years, the code-base is a sprawling,
hideous, unmaintainable nightmare.&lt;/p&gt;

  &lt;p&gt;Which language do you pick?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You’re not allowed to cheat. You have to pick a language you’d use for
a real project. You can’t choose assembly language, and you certainly
can’t choose &lt;a href=&quot;http://en.wikipedia.org/wiki/Brainfuck&quot;&gt;Brainfuck&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think this is an interesting way of thinking about the question for
two reasons. First, whilst we spend so much of our time as programmers
maintaining code, we spend surprisingly little time talking about
maintenance. Or thinking about it. And second, the question isn’t,
“Which is the least maintainable language?”, but rather, “Which
languages tends to encourage the least maintainable behaviour?”&lt;/p&gt;

&lt;p&gt;I think I’ve made my choice. I think I’m picking Perl.&lt;/p&gt;

&lt;p&gt;Now don’t get me wrong, I like Perl a lot. I seem to like Perl more
than most people I meet. It’s particularly strong at text-handling,
and makes a good choice when you’re forced to resort to
screen-scraping semi-structured data.&lt;/p&gt;

&lt;p&gt;But Perl does not lend itself well to large, clear code bases. It has
a good object model, but it doesn’t enforce it. It doesn’t even really
recommend it. It’s just there in case anyone’s interested.&lt;/p&gt;

&lt;p&gt;It has something like a recommended project structure, but unless
you’re producing modules for CPAN or you’ve stumbled upon the object
model, you’ll probably miss it.&lt;/p&gt;

&lt;p&gt;And worst of all there’s very little unity of approach. Ask five Java
programmers to write a simple program, and by-and-large all five of
them will come up with a similar answer. Ask five Perl programmers,
and they’ll all have a different preferred approach. And they’ll
probably all take pride in how novel their solution is. That’s all
good fun, but having five ways to do the same simple thing doesn’t
lend itself to large scale coding.&lt;/p&gt;

&lt;p&gt;I could pick other languages. The worst coding crimes I’ve ever seen
have all been in PHP. But for an absolute lack of unity, I’m picking
Perl.&lt;/p&gt;

&lt;p&gt;What would you pick?&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Naming Things</title>
		  <pubDate>Sun, 06 Nov 2011 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2011/11/naming-things.html</link>
		  <guid>http://blog.jenkster.com/2011/11/naming-things.html</guid>
		  <description>&lt;p&gt;Yesterday we went to a toy store called Fun Junction. I think this is
a terrible name. To me, Fun Junction is the point where Fun &amp;amp; No Fun
meet…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Because the Kids are Lighting Fireworks Already</title>
		  <pubDate>Thu, 03 Nov 2011 00:00:00 +0000</pubDate>
		  <link>http://blog.jenkster.com/2011/11/because-kids-are-lighting-firework.html</link>
		  <guid>http://blog.jenkster.com/2011/11/because-kids-are-lighting-firework.html</guid>
		  <description>&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Remember, remember the 3rd of November,
Blowing things up is a lark,
I don't care a jot about gunpowder plot,
I'm off to light fires in the park...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>Internet Explorer to Enter the Deadpool</title>
		  <pubDate>Sun, 04 Sep 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/09/internet-explorer-to-enter-deadpool.html</link>
		  <guid>http://blog.jenkster.com/2011/09/internet-explorer-to-enter-deadpool.html</guid>
		  <description>&lt;p&gt;In a surprise move, Microsoft have today announced that they’re
getting out of the browser game. “It’s time to call it a day,” said a
Microsoft spokesperson. “We’ve been working on Internet Explorer for
over fifteen years now,
and
&lt;a href=&quot;http://37signals.com/svn/posts/2988-i-thought-internet-explorer-9-was-supposed&quot;&gt;we still can’t render basic layouts reliably&lt;/a&gt;.”&lt;/p&gt;

&lt;p&gt;“‘Does it work in IE yet?’ has become a stock question for web
developers around the globe, and it’s getting embarrassing.”&lt;/p&gt;

&lt;p&gt;“It’s time we left the browser game to the professionals, and focussed
on what we’re good at: rearranging the menu bar in Word every 6
months.”&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>How To Get X11 Working On An EC2 AMI</title>
		  <pubDate>Wed, 17 Aug 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/08/how-to-get-x11-working-on-ec2-ami.html</link>
		  <guid>http://blog.jenkster.com/2011/08/how-to-get-x11-working-on-ec2-ami.html</guid>
		  <description>&lt;p&gt;It’s actually pretty easy, but worth noting:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh ec2-user@ec2machine
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;xauth xeyes
&lt;span class=&quot;nb&quot;&gt;exit

&lt;/span&gt;ssh &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; ec2-user@ec2machine
xeyes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In short, the magic’s in installing Xauth and then re-logging in with
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -X&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;And I admit, xeyes isn’t strictly necessary, but I find it’s a nice,
lightweight confirmation that both display and mouse are working as
expected.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Diagnosing Problems On The Web - A Rule Of Thumb</title>
		  <pubDate>Wed, 03 Aug 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/08/diagnosing_problems_on_the_internet.html</link>
		  <guid>http://blog.jenkster.com/2011/08/diagnosing_problems_on_the_internet.html</guid>
		  <description>&lt;p&gt;My mother is asking for technical support ‘for a friend’. She’s
reminded me of this quick diagnostic tip that’s worth noting:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Geek: What browser are you using?
Patient: What's a browser?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They’re using Internet Explorer. Someone might have installed a better
browser for them, but if they had someone like that in their lives,
they wouldn’t turn to you for tech support.&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Vim vs. Emacs - The War Is Over</title>
		  <pubDate>Mon, 01 Aug 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/08/vim-vs-emacs-war-is-over.html</link>
		  <guid>http://blog.jenkster.com/2011/08/vim-vs-emacs-war-is-over.html</guid>
		  <description>&lt;p&gt;Vim is the greatest text editor in the
world.
&lt;a href=&quot;/2012/06/programmers-your-text-editor-wasnt.html&quot;&gt;I have strong opinions about why this is so&lt;/a&gt;,
and why Eclipse &amp;amp; co.’s editors are inadequate by design, but that’s
for another day. No, this is just a quick post to say the Vim
vs. Emacs wars are over. I’m a Vim user, but if you like Emacs that’s
just fine with me. We mustn’t fight. We must save our energy. There
are people out there writing code in Notepad FFS…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Star Pelican</title>
		  <pubDate>Sat, 30 Jul 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/07/star-pelican.html</link>
		  <guid>http://blog.jenkster.com/2011/07/star-pelican.html</guid>
		  <description>&lt;p&gt;I &lt;em&gt;think&lt;/em&gt; I’m blogging again. Certainly the current frequency of posts
would imply I am. And if I’m blogging again, I’m doing it because
there are thoughts that are too public for Facebook &amp;amp; too long for
Twitter. Thoughts like,
“&lt;a href=&quot;/2011/07/native-apps-vs-web-apps.html&quot;&gt;Google’s webapps are so good that they show webapps are doomed.&lt;/a&gt;”
And non-technical thoughts too, like, “In the future, Pelicans will be
armed.”&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/star-pelican.jpg&quot; alt=&quot;Star Pelican&quot; /&gt;&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>Native Apps vs Web Apps</title>
		  <pubDate>Fri, 29 Jul 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/07/native-apps-vs-web-apps.html</link>
		  <guid>http://blog.jenkster.com/2011/07/native-apps-vs-web-apps.html</guid>
		  <description>&lt;p&gt;An interesting question at the moment is, should I build native iOS &amp;amp;
Android apps, or build one webapp to rule them all? There are pros and
cons to each. Most of the arguments are obvious and well-trodden, but
here’s one point that’s important and not being said: Google.&lt;/p&gt;

&lt;p&gt;Google have put their stake in the ground and are investing heavily in
the webapp route. Their Gmail &amp;amp; Google+ clients are are easily the
most advanced mobile webapps in the game. And do you know what?
They’re still a bit rubbish. They’re a bit slow. They’re a bit
flakey. They all have the, “This looked really good in the lab”, feel
to them.&lt;/p&gt;

&lt;p&gt;Google’s webapps are “impressive, for a webapp”, which is like saying,
“he’s cool, for a geek”. A qualified compliment isn’t much of a
compliment at all. I really want them to succeed, and they’re doing an
amazing job, but for all their effort I still go to the app store to
find the &lt;em&gt;real&lt;/em&gt; app.&lt;/p&gt;

&lt;p&gt;If Google, with all their talent and resources, can push the
possibilities of webapps and we still need to offer excuses, maybe
that says it’s not the way to go…&lt;/p&gt;
</description>
		</item>
    
		<item>
		  <title>OSX Apps I Can't Live Without</title>
		  <pubDate>Wed, 27 Jul 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/07/osx-apps-i-cant-live-without.html</link>
		  <guid>http://blog.jenkster.com/2011/07/osx-apps-i-cant-live-without.html</guid>
		  <description>&lt;p&gt;Frabjous day - I have a new laptop. I’d been waiting for ages for the
next model of MacBook Air to be released, so I pounced at the
weekend. And I think that makes it time for the geekblogger’s
favourite: the “OSX Apps I Install First” list. I’ll avoid the obvious
ones like Chrome, Spotify, Dropbox &amp;amp; XCode, and skip straight to the
meat. Hopefully there’s something here you haven’t heard of before
that you can try…&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Do you like Terminal, Spotlight or Chrome’s universal search feature?
 Then Alfred is for you. It’s a fast app-launcher, file-finder &amp;amp;
 web-searcher that’s absolutely the first thing I put on every
 Mac. More flexible than Spotlight, faster than QSB and currently
 thriving (unlike the almost-zombie Quicksilver), I can’t recommend it
 enough.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/alfred-logo-small.png&quot; alt=&quot;Alfred Logo&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.backblaze.com/partner/af4609&quot;&gt;Backblaze&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;We were burgled last year. My laptop - my working life - was taken. I
 had Time Machine backups, and I got lucky (they didn’t steal my
 external hard drive) so I got it all back. But never again will I risk
 my music &amp;amp; my photos&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; on the laziness of thieves.&lt;/p&gt;

    &lt;p&gt;In the weeks following the burglary I tried several off-site backup
 solutions&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. BackBlaze is the bee’s knees. It’s written by ex-Apple
 employees, and it shows. Actually, it hides. It just sits quietly in
 the background ensuring that my data’s always backed up to a second
 country. It also does second duty as a poor man’s version control
 system, and third duty as a find-if-stolen service. But it’s
 absolutely, 100% worth the price of a latte a month. Get it.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/backblaze-logo-small.jpg&quot; alt=&quot;Backblaze Logo&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.pixelmator.com/&quot;&gt;Pixelmator&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;I’m not a graphic designer. I’ll never be a graphic designer. So I
 can’t tell you exactly how Pixelmator compares to Photoshop. I can
 tell you that it does more than everything I need, it’s about 95%
 cheaper than Photoshop, and it’s one of the most polished pieces of
 software I’ve ever used.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/pixelmator-logo-small.png&quot; alt=&quot;Pixelmator Logo&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;My ‘hobby’ iPad app, &lt;a href=&quot;http://itunes.jenkster.com/time-for-tea&quot;&gt;Time for Tea&lt;/a&gt;, was
 designed in Pixelmator and I think the result is pretty good (for a
 non-graphic designer):&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/time_for_tea_ipad.png&quot; alt=&quot;Time for Tea&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;(That’s the current peak of my design skills. Any shortcomings are mine, not Pixelmator’s.)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Of course all my work is backed up again to remote git repositories, but you guessed that, right? &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Mozy sucks, by the way. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
		</item>
    
		<item>
		  <title>London 2012, One Year To Go</title>
		  <pubDate>Wed, 27 Jul 2011 00:00:00 +0100</pubDate>
		  <link>http://blog.jenkster.com/2011/07/london-2012-one-year-to-go.html</link>
		  <guid>http://blog.jenkster.com/2011/07/london-2012-one-year-to-go.html</guid>
		  <description>&lt;p&gt;Wow! I just found out I’ve been elected as Chairman Of The Olympic
Committee For Getting People Who Don’t Give A Stuff About The Olympics
To Give A Stuff About The Olympics.&lt;/p&gt;

&lt;p&gt;My first campaign will be, “Come To London in 2012: The Aquarium Will
Still Be Ace.”&lt;/p&gt;

&lt;p&gt;I’ll follow up with my second campaign, “Enjoyed The Aquarium? You
Could Watch Some Humans Swim Next, I Suppose.”&lt;/p&gt;
</description>
		</item>
    

  </channel>
</rss>
