<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kirk Shillingford</title>
    <description>The latest articles on Forem by Kirk Shillingford (@kirkcodes).</description>
    <link>https://forem.com/kirkcodes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F64350%2F2873bc42-62f8-4aba-9950-3f24e8a56308.jpg</url>
      <title>Forem: Kirk Shillingford</title>
      <link>https://forem.com/kirkcodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kirkcodes"/>
    <language>en</language>
    <item>
      <title>From Script to Scaffold in F#</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Sat, 24 Dec 2022 00:03:29 +0000</pubDate>
      <link>https://forem.com/kirkcodes/from-script-to-scaffold-in-f-1phh</link>
      <guid>https://forem.com/kirkcodes/from-script-to-scaffold-in-f-1phh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FtAeB6dptxnoli%2Fgiphy." class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FtAeB6dptxnoli%2Fgiphy." alt="scaffolding" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This year I've been attempting &lt;a href="https://adventofcode.com/" rel="noopener noreferrer"&gt;Advent of Code&lt;/a&gt; in my favourite programming language, &lt;a href="https://fsharp.org/" rel="noopener noreferrer"&gt;F#&lt;/a&gt;. This is a beginner(ish) centered post about making incremental changes from the smallest possible solution to something more robust.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is F# (F Sharp)
&lt;/h3&gt;

&lt;p&gt;If you've never heard of it before, F# is a &lt;em&gt;functional first&lt;/em&gt; programming language in the &lt;a href="https://dotnet.microsoft.com/en-us/" rel="noopener noreferrer"&gt;Microsoft dotnet&lt;/a&gt; ecosystem used for general purpose programming, Web development, data analysis, and everything in between. It compiles to the same &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/clr" rel="noopener noreferrer"&gt;Common Language Runtime&lt;/a&gt; as all other .NET languages, meaning it can interop with any C# package//library and make full use of the .NET ecosystem.&lt;/p&gt;

&lt;p&gt;More importantly, (to me), it's a delightfully expressive language, that has just about &lt;em&gt;every semantic pattern I enjoy in a modern programming language&lt;/em&gt;, like &lt;a href="https://fsharpforfunandprofit.com/posts/type-size-and-design/" rel="noopener noreferrer"&gt;algebraic data types&lt;/a&gt;, powerful &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching" rel="noopener noreferrer"&gt;pattern matching&lt;/a&gt; capabilties, &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/functional-programming-concepts" rel="noopener noreferrer"&gt;immutability as a default&lt;/a&gt;, and a generally terse, lightweight syntax, which both functional and &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/classes" rel="noopener noreferrer"&gt;Object Oriented&lt;/a&gt; patterns a delight to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Advent of Code
&lt;/h3&gt;

&lt;p&gt;If you're unfamiliar with it, Advent of Code (or AOC as we'll be referring to it from now on) is a yearly programming challenge that takes place from the first to the 25th of December. Each day a themed coding puzzle is released, in increasing order of difficulty. Programmers from all over the world attempt to solve these puzzles, with varying degrees of competitiveness and rigour. For example, as of writing this in 2022, over &lt;a href="https://adventofcode.com/2022/stats" rel="noopener noreferrer"&gt;two hundred thousand participants&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have zero interest in the hyper-competitive aspect of AOC; my current life does not afford me the opportunity to do programming challenges in the wee hours of the night. However, this year, after beginning the way I normally do AOC, writing one-off scripts each day, I began feeling frustrated with how much time I spent &lt;em&gt;erecting structures to make solutions possible&lt;/em&gt;, vs actually solving problems.&lt;/p&gt;

&lt;p&gt;Earlier this year, I wrote about scripting and automation in &lt;a href="https://dev.to/kirkcodes/scripting-with-vscode-tasks-and-typescript-38h7"&gt;VSCode using typescript&lt;/a&gt; as part of an ongoing project to reduce time consuming repetitive actions in my professional life. So this seemed like a perfect opportunity to do something similar at a more targeted domain space. Additionally, I'd seen a few examples of AOC runners floating around (pre-built libraries and templates that come with hope to help streamline the mechanics of participating in AOC). There are &lt;a href="https://github.com/eduherminio/AdventOfCode.Template" rel="noopener noreferrer"&gt;a&lt;/a&gt; &lt;a href="https://github.com/mMosiur/AdventOfCodeDayTemplate" rel="noopener noreferrer"&gt;few&lt;/a&gt; &lt;a href="https://github.com/sindrekjr/AdventOfCodeBase" rel="noopener noreferrer"&gt;solutions&lt;/a&gt; in the .NET ecosystem, but they're all in C#!&lt;/p&gt;

&lt;p&gt;There's nothing &lt;em&gt;wrong&lt;/em&gt; with C# mind you, but I'm here this year, to write F#, not C#. So without any more pre-ample, I'd like to share some of the things I've implemented so far and the trajectory for my AOC runner and solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;warning&lt;/strong&gt;: I've used snippets from past and current solutions as examples for the article. It &lt;em&gt;shouldn't&lt;/em&gt; be enough to provide meaningful spoilers for anyone, but if your goal is to try the problems, and you're worried about any sort've input, you've been warned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0 - The current state of things
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxy4zz9s4tdtis61ofi6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxy4zz9s4tdtis61ofi6.gif" alt="where are we" width="500" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the things I love about F# is its power as a &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/tools/fsharp-interactive/" rel="noopener noreferrer"&gt;scripting language&lt;/a&gt; and with the start of this year's AOC, I took full advantage of this. With access to the F# interactive REPL, my initial pattern was to simply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create each day as a &lt;code&gt;.fsx&lt;/code&gt; file called &lt;code&gt;DayXX.fsx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Each AOC problem is split into two parts, so after completing each portion, I would simply print my solution to console.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""

...

"""&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;day10part1solution&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;tokenize&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryFindBack&lt;/span&gt; &lt;span class="n"&gt;isInvalid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sumBy&lt;/span&gt; &lt;span class="n"&gt;invalidValue&lt;/span&gt;

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

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;day10part2solution&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;tokenize&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;isInvalid&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryFindBack&lt;/span&gt; &lt;span class="n"&gt;isIncomplete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unfold&lt;/span&gt; &lt;span class="n"&gt;deTokenize&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;toNum2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nc"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;middle&lt;/span&gt;

&lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;"{day03part1solution}, {day03part2solution}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be able to see the obvious problems with this approach over time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I manually copy and paste all inputs from AOC into the file itself which is clunky and error-prone. It also means more hot swapping of comments when doing tests&lt;/li&gt;
&lt;li&gt;Toggling the output I focus on involves modifying an interpolated string&lt;/li&gt;
&lt;li&gt;Because the solutions are values and not functions, unless commented out, they're both calculated anyway, which is an issue for solutions involving a heavier amount of calculations.&lt;/li&gt;
&lt;li&gt;You can't see it, but because I just make a new script for each day, I'm doing &lt;strong&gt;a lot&lt;/strong&gt; of rewriting of useful patterns. I &lt;em&gt;could&lt;/em&gt; make yet another script for those things I want to repeat, but at that point, I may as well just overhaul the entire solution, which is exactly what we're gonna do.&lt;/li&gt;
&lt;li&gt;Lastly, &lt;code&gt;.fsx&lt;/code&gt; aren't ideal for using official testing frameworks like &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-fsharp-with-dotnet-test" rel="noopener noreferrer"&gt;Xunit&lt;/a&gt;, &lt;a href="https://fsprojects.github.io/FsUnit/xUnit.html" rel="noopener noreferrer"&gt;FsUnit&lt;/a&gt;, or &lt;a href="https://github.com/SwensenSoftware/unquote" rel="noopener noreferrer"&gt;Unquote&lt;/a&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 - Switching to solutions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgr9eajsctaqo7hphmlc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgr9eajsctaqo7hphmlc.gif" alt="Big Problems Actually Have Very Simple Solutions" width="480" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Firstly we can easily use the dotnet &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/tools/" rel="noopener noreferrer"&gt;command line interface&lt;/a&gt; to scaffold a &lt;em&gt;solution&lt;/em&gt; with a new project for all our solutions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new sln &lt;span class="nt"&gt;-o&lt;/span&gt; AOC
dotnet new console &lt;span class="nt"&gt;-lang&lt;/span&gt; &lt;span class="s2"&gt;"F#"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; AOC2022
dotnet sln add AOC2022/AOC2022.fsproj

&lt;span class="nb"&gt;mkdir &lt;/span&gt;AOC2022.Tests
&lt;span class="nb"&gt;cd &lt;/span&gt;AOC2022.Tests
dotnet new xunit &lt;span class="nt"&gt;-lang&lt;/span&gt; &lt;span class="s2"&gt;"F#"&lt;/span&gt;
dotnet add reference ../AOC2022/AOC2022.fsproj
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
dotnet sln add AOC2022.Tests/AOC2022.Tests.fsproj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a little bit going on but essentially these commands just:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make a new solution called AOC&lt;/li&gt;
&lt;li&gt;Add a project called AOC2022 that contains our code for our actual solutions&lt;/li&gt;
&lt;li&gt;Make a project called AOC2022.Tests that'll consume our AOC code and run tests on our solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now for our &lt;code&gt;.fsx&lt;/code&gt; files. First, we'll place them all in our new &lt;code&gt;AOC2022&lt;/code&gt; folder as part of the project and we'll change them to &lt;code&gt;fs&lt;/code&gt; files (which is the file type dotnet can parse into a proper solution. Additionally, we'll make a few tweaks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Day03&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt; 

&lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;part1&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;tokenize&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryFindBack&lt;/span&gt; &lt;span class="n"&gt;isInvalid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sumBy&lt;/span&gt; &lt;span class="n"&gt;invalidValue&lt;/span&gt;

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

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;part2&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;tokenize&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;isInvalid&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryFindBack&lt;/span&gt; &lt;span class="n"&gt;isIncomplete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unfold&lt;/span&gt; &lt;span class="n"&gt;deTokenize&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;toNum2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nc"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;middle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file now has a unique &lt;code&gt;module&lt;/code&gt;, which is the primary way of organizing code in .NET. Think &lt;em&gt;Solution -&amp;gt; Project -&amp;gt; Namespace (Optional) -&amp;gt; Module -&amp;gt; Value&lt;/em&gt;. Instead of the parts being values, they're now functions that accept the data as input and perform the appropriate calculations. We can call them by saying &lt;code&gt;DayXX.part1 input&lt;/code&gt;... for example. And that makes it a lot easier to use and test them.&lt;/p&gt;

&lt;p&gt;Yay, more structure! There's just one problem! We now have no way of actually running our problem files. Let's fix that with some more CLI work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Passing Arguments through the Command Line
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwmc5cb8pqbtkd7t3lyn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwmc5cb8pqbtkd7t3lyn.gif" alt="highly cogent arguments" width="480" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that out code is &lt;code&gt;.fs&lt;/code&gt; files, we have no way of calling them directly from the command line. In the &lt;em&gt;entrypoint&lt;/em&gt; of our application, &lt;code&gt;Program.fs&lt;/code&gt;, we could simply call and return every value in our files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;day1input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;day2input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;day3input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;// printfn $"{Day01.part1 day1input}, {Day01.part2 day1input}"&lt;/span&gt;
&lt;span class="c1"&gt;// printfn $"{Day02.part1 day2input}, {Day02.part2 day2input}"&lt;/span&gt;
&lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;"{Day03.part1 day3input}, {Day03.part2 day3input}"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but this still means we're doing control flow with comments. We can do better.&lt;/p&gt;

&lt;p&gt;One of the things I've been experimenting with a bit more recently are &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions#:~:text=Computation%20expressions%20in%20F%23%20provide,monad%20transformers%2C%20and%20applicative%20functors." rel="noopener noreferrer"&gt;Computation Expressions&lt;/a&gt; which for the purposes of this post we can just treat as ways of safely transforming data in context while keeping a convenient procedural syntax. Using one little CE for the &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/options#:~:text=The%20option%20type%20in%20F%23,might%20not%20have%20a%20value." rel="noopener noreferrer"&gt;Option type&lt;/a&gt; we can put together a crude mechanism to capture user input on the solutions we want to run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IO&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getInput&lt;/span&gt; &lt;span class="n"&gt;dayNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;"./data/day{dayNumber}.txt"&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReadAllLines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="nc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getSolution&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Day01&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Day01&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Day02&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Day02&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"3"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Day03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Day03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;MaybeBuilder&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Zero&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;maybe&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MaybeBuilder&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;

&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EntryPoint&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;maybe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryHead&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tryItem&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getInput&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getSolution&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;

        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"%A"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"%A"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"%A"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"%A"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ignore&lt;/span&gt;

    &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, let's take a step back and talk about what we're doing here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We've made a function &lt;code&gt;getInput&lt;/code&gt; that accepts a string and tries to find a txt file based on that string. We're going to start keeping our input data in a folder called data, and keep our &lt;code&gt;.fs&lt;/code&gt; files containing just our solution code. The function will check if the file exists, and if it does, try and read all the lines into an array of strings&lt;/li&gt;
&lt;li&gt;We've also made a &lt;code&gt;getSolution&lt;/code&gt; function that attempts to get a solution based on an input string. If we try to call a solution we haven't created yet, it'll just return a value of &lt;code&gt;None&lt;/code&gt; instead of crashing.&lt;/li&gt;
&lt;li&gt;Our last special value is a &lt;code&gt;MaybeBuilder&lt;/code&gt; computation expression. Rather than explain it here, we'll just talk through how it's used below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our &lt;code&gt;main&lt;/code&gt; function, we put it all together, plus attempting to access two values from the incoming arguments to the program, &lt;code&gt;day&lt;/code&gt; and &lt;code&gt;part&lt;/code&gt; values representing what code we want to run and what day we want to run it. Those &lt;code&gt;let!&lt;/code&gt;s reference any value that would normally be an option and let us use them as if the were just normal values. Our &lt;code&gt;MaybeBuilder&lt;/code&gt; is doing the work of chaining the valid values in the background. If any of these actions returns a None, the whole thing gracefully returns None and won't crash. It's not particularly informative, but this is just for me, and all I really want is to not handle crazy error messages every time I mistype a day or part name. &lt;/p&gt;

&lt;p&gt;Mind you, a construct like maybe builder is absolutely unnecessary. This was just my small attempt at IO safety. I may switch to a more formal method using &lt;a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/async-expressions" rel="noopener noreferrer"&gt;async expressions&lt;/a&gt;. Or just handling the logic using regular, practical if expressions. Whatever works. &lt;/p&gt;

&lt;p&gt;Anyways, we did all of this just so in our terminal we can run our solutions individually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run 3 1 

// part 1 results

dotnet run 3 2

// part 2 results

dotnet run 3

// part 1 results
// part 2 results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! This is looking way more organized! And most of our earlier hiccups are gone. All we need now are some tests!&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 3 - All the Tests
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz13uibpo532m83xwvru.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz13uibpo532m83xwvru.gif" alt="this is a test" width="500" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've done a bit of setup so far so we just need a few things to get our tests working&lt;/p&gt;

&lt;p&gt;First, we need some test files. We'll mirror the project setup in our AOC2022 folder, one file/module per day, and a data file for test inputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Day03Tests&lt;/span&gt;

&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;Xunit&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;getInput&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;failwith&lt;/span&gt; &lt;span class="s2"&gt;"Input cannot be found"&lt;/span&gt; 

&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;``Part 1``&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;157&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Day03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part1&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;``Part 2``&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Day03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've kept the tests pretty simple for now. We reuse the &lt;code&gt;getInput&lt;/code&gt; function from our AOC2022 project but this type we deliberately throw an error if it's missing, since I'm not doing any manual typing with these tests. Then we simply call our module functions in our tests, and compare them to our expected values. We can run these tests from our solution folder just be saying.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet test --filter Day03Tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note here the built in functionality to filter tests to one specific module. (And we can of course omit the filter and run all the tests).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;last&lt;/em&gt; thing we need is just a little tweak to our &lt;code&gt;AOC2022.Tests.fsproj&lt;/code&gt; file so those data files are included in our output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt;
  &amp;lt;Compile Include="*.fs" /&amp;gt;
  &amp;lt;Content Include="data\**"&amp;gt; 

  &amp;lt;CopyToOutputDirectory&amp;gt;PreserveNewest&amp;lt;/CopyToOutputDirectory&amp;gt;
  &amp;lt;/Content&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This little contant tag in our XML ensures all the data successfully makes to our build directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Next Steps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5elhw6nz9y9s464xsam.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5elhw6nz9y9s464xsam.gif" alt="Bye guys" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've made it here you've seen all I wanted to share in this post. This project is &lt;em&gt;far&lt;/em&gt; from over, and I almost didn't share this post because I wanted to add &lt;strong&gt;a lot&lt;/strong&gt; more features first, but I revised that after thinking about how it's rare to see conversations about work in progress. I'm hoping that seeing a project go from nothing to something could provide value for some people. Also, this is a living project and I am using and solving advent of code in it, so my time is split between doing more scaffolding and well, solving problems.&lt;/p&gt;

&lt;p&gt;Things coming soon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic file generation for each day&lt;/li&gt;
&lt;li&gt;More formal argument parsing using the &lt;a href="https://fsprojects.github.io/Argu/" rel="noopener noreferrer"&gt;Argu library&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Automatic input downloads &lt;/li&gt;
&lt;li&gt;Benchmarking tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can view the live project (and my solves for AOC 2022) &lt;a href="https://github.com/tkshill/AdventOfCode2022/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>Scripting with VSCode Tasks and Typescript</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Wed, 16 Nov 2022 18:01:55 +0000</pubDate>
      <link>https://forem.com/kirkcodes/scripting-with-vscode-tasks-and-typescript-38h7</link>
      <guid>https://forem.com/kirkcodes/scripting-with-vscode-tasks-and-typescript-38h7</guid>
      <description>&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@markuswinkler?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Markus Winkler&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/script?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article will attempt to demonstrate the minimum setup required to run Typescript scripts through Node using VSCode Tasks. We're going to create from scratch a small project that allows someone to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write some Typescript&lt;/li&gt;
&lt;li&gt;Run that Typescript without converting it to Javascript first&lt;/li&gt;
&lt;li&gt;Run the entire process using VSCode tasks to capture user arguments without using the command line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The article assumes a passing familiarity with &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt;, and &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, but I've tried to include links wherever someone might want additional context. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Note&lt;/strong&gt;: This article is meant to be more of a how-to than a why-to, but I felt like it was worth talking about the &lt;em&gt;reason&lt;/em&gt; behind scripting in the general, and Typescript in particular. If you'd rather jump straight to the implementation though, you can head straight there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why script in Typescript? Why script at all?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejvtface3pqfspj3wkrf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejvtface3pqfspj3wkrf.gif" alt="Medical professional asking why"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, I've been taking a hard look at my work patterns, and making note of opportunities for improvement. What I've discovered are a large amount of repetitive tasks that are made &lt;em&gt;unnecessarily inconsistent and haphazard&lt;/em&gt; because I do them from scratch whenever I need them, with little preparation.&lt;/p&gt;

&lt;p&gt;I don't think all tasks require automation, and there's a real measure of "value-gained-per-time-lost" that should always be considered, but at least for me personally, it feels like a space where I can make meaningful changes to great benefit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Scripting_language" rel="noopener noreferrer"&gt;Scripting&lt;/a&gt; can be a great way to reduce cognitive overhead and save time by automating away actions that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repetitive, meaning the same actions take place with sufficient frequency and duration that there's a significant chunk of your time repeating the same actions.&lt;/li&gt;
&lt;li&gt;Tediously Mechanical, meaning actions that require specificity and precision, but not analysis (long sequences of commands, file creation and naming, migration of text, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Often we associate scripts with the built-in environments that interface with our operating systems, like &lt;a href="https://www.gnu.org/software/bash/manual/html_node/What-is-Bash_003f.html" rel="noopener noreferrer"&gt;bash&lt;/a&gt; or &lt;a href="https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.3" rel="noopener noreferrer"&gt;Powershell&lt;/a&gt;, but we can use any language for scripting provided it has some mechanism (like a &lt;a href="https://en.wikipedia.org/wiki/Runtime_system" rel="noopener noreferrer"&gt;runtime environment&lt;/a&gt; for executing instructions on a server/OS.&lt;/p&gt;

&lt;p&gt;Frequently in my experience, scripts have been described and treated as short, throwaway code, or tedious config work, devoid of the care and rigour we apply to application or operations code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But if something is important enough to commit to code, it's probably important enough to try to write correctly.&lt;/strong&gt; The paradigms of readability, testability, and extensibility are just as relevant for short, targeted actions as long-standing operations. Maybe even more so?&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter Typescript
&lt;/h3&gt;

&lt;p&gt;Anyone who knows me knows I have a deep fondness for &lt;a href="https://blog.ploeh.dk/2015/08/10/type-driven-development/" rel="noopener noreferrer"&gt;Type Driven Development&lt;/a&gt; and a particular fascination with &lt;a href="https://www.learningtypescript.com/articles/extreme-explorations-of-typescripts-type-system#:~:text=TypeScript%27s%20type%20system%20is%20Turing,variables%2C%20functions%2C%20and%20recursion." rel="noopener noreferrer"&gt;Typescript's Type system&lt;/a&gt;. Many folks do not see the value in static type systems and I don't see the value in refuting those opinions; I can only attempt to express my own satisfaction through the work I do. I try as much as possible to write code with the support of a strong type system whenever I am able to, and for me, the benefits are real and worthwhile. So this is for anyone who might be interested in the same.&lt;/p&gt;

&lt;p&gt;Also, just as a personal note, &lt;em&gt;I love writing scripts.&lt;/em&gt; I love writing short, powerful, durable piece of code, that do a thing, well. I like the completeness of small actions, done well. Scripts make me &lt;em&gt;happy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Manually debugging scripts though, does not make me happy. It does not spark joy. There is a wailing and gnashing of teeth. So I want every possible safeguard to ensure my scripts work as well as they can the first time around. I'm not under the delusion that I can prevent all errors before I run the code. I'd just like to prevent &lt;em&gt;some&lt;/em&gt; of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Our Scripts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/f6z5TkrTIBZILYOd1t/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/f6z5TkrTIBZILYOd1t/giphy.gif" alt="Man excitedly saying "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're going to split this into two major parts; firstly, how to run typescript code in node without prior compilation to js, and then how to configure that process using a Visual Studio Code Tasks features.&lt;/p&gt;

&lt;p&gt;First step is ensuring we have both Node and Visual Studio Code on your machine. I'm going to create a new project folder and open it up in VSCode. We won't need VSCode till we implement tasks though, so working in a File Explorer or Terminal is also fine.&lt;/p&gt;

&lt;p&gt;In our project folder, we're going to create our first file, &lt;code&gt;createTemplate.ts&lt;/code&gt; that contains the code we want to execute.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writeFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cwdInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dateInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawDay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawDay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rawDay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTimezoneOffset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-CA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
&lt;span class="s2"&gt;`
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-CA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;weekday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="s2"&gt;

# Gratitude
-
-
-

# Frogs
-
-
-

# Wins
-
-
-
`&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// writeFile(path, template, console.log)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This script creates a markdown file with some prewritten headers that I tend to use when I write my daily journals. It then sticks that file in the current working directory, with some context of the current date. Currently, we're just opting to log it console first though, while we're getting setup.&lt;/p&gt;

&lt;p&gt;As it stands, it currently works fine, but we have two problems.&lt;/p&gt;

&lt;p&gt;First, we're getting some rudimentary, and dubious type hints right now. We're being told that the command line arguments &lt;code&gt;cwdInput&lt;/code&gt; and &lt;code&gt;dateInput&lt;/code&gt; are strings, but there's actually no guarantee that they're there at all. &lt;code&gt;process.env&lt;/code&gt; pulls info from the environment the script is run in, and thus is an I/O operation, which is inherently impure. Typescript has the capacity to warn us about this, but isn't currently configured to surface that, so let's give it that capacity.&lt;/p&gt;

&lt;p&gt;We can add a &lt;code&gt;tsconfig.json&lt;/code&gt; file that informs VSCode's typescript language server of how we want it to compile our code, and what guarantees we'd like. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES2021"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"noUnusedLocals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CommonJS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NodeNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ES2021"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"noUncheckedIndexedAccess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;We've got a few things in there, but most important is the &lt;code&gt;strict: true&lt;/code&gt; and &lt;code&gt;noUncheckedIndexedAccess: true&lt;/code&gt;, configuration. This makes the compiler much less permissive about unsafe operations and our intellisence now correctly sees that our process values are &lt;code&gt;string | undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you've been following along directly, your project folder should now look like,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43p7dq47si8wkuqi9pry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43p7dq47si8wkuqi9pry.png" alt="Folder with a single typescript file, a tsconfig file and the example configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  But how to run it
&lt;/h3&gt;

&lt;p&gt;The second problem we've got with this script right now is of course, we've got nothing to run it! Because Node can't directly run Typescript! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To be clear, there is currently no popular runtime engine for Typescript. Meaning, there is no application that accepts Typescript natively, turns it to an &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;AST&lt;/a&gt;, and executes in an environment, without &lt;em&gt;first, compiling it to javascript&lt;/em&gt;. That's what Typescript &lt;em&gt;is&lt;/em&gt; really:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An expanded syntax and type system that layers over Javascript syntax, providing an powerful set of additional information, context, and guarantees at compile time&lt;/li&gt;
&lt;li&gt;A compiler than converts that to javascript to be consumed by some runtime.&lt;/li&gt;
&lt;li&gt;A language itself for expressing complex shapes and a powerful engine for type manipulation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typically, we would compile our Typescript to Javascript, and run those javascript files with Node. But in this case, we don't need to ever use those javascript files. And this code isn't going to the browser either. So we have the option of finding solutions that don't need those intermediate javascript files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ts-Node
&lt;/h3&gt;

&lt;p&gt;The one we're going to use is &lt;a href="https://typestrong.org/ts-node/" rel="noopener noreferrer"&gt;ts-node&lt;/a&gt;. Ts-node has a simple premise; you can pass it typescript files, and it will convert them to JS, and pass them to node for you. It can function also function as a REPL.&lt;/p&gt;

&lt;p&gt;To get it, we first add a &lt;code&gt;package.json&lt;/code&gt; to our directory. A lot of folks think you need a filled out package.json for npm to function effectively. But really you just need the file.&lt;/p&gt;

&lt;p&gt;We can then install the necessary packages using the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm i &lt;span class="nt"&gt;-D&lt;/span&gt; typescript ts-node


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That will install ts-node and the Typescript compiler locally, as dev-dependencies. There's an argument for having these as just regular dependencies here, but we're not planning to ship this code anywhere else, so I'm not sure what the best practise is (if anyone reading has opinions, please let me know!)&lt;/p&gt;

&lt;p&gt;So we should now see something like this in out &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ts-node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^10.9.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.8.4"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;Check in time for those following along! Now your project folder should look like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsje6klwvcmt506u3nv76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsje6klwvcmt506u3nv76.png" alt="Image showing project folder with the addition of a package.json, and node modules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've added a little addition to our &lt;code&gt;tsconfig&lt;/code&gt; to tell &lt;code&gt;ts-node&lt;/code&gt; to &lt;strong&gt;not&lt;/strong&gt; run type-checking on our code, because the language intellisense in VSCode is already doing that for us. We've also added some controls to ensure Typescript doesn't attempt to output any javascript files.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES2021"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"noUnusedLocals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"noEmit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CommonJS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NodeNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ES2021"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"noUncheckedIndexedAccess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ts-node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"transpileOnly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;And now we can simply tell ts-node to run our typescript using &lt;a href="https://www.npmjs.com/package/npx" rel="noopener noreferrer"&gt;npx&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx ts-node createTemplate.ts /path/to/root/ 2022-11-15


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And we get the result we want!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82d42qko7b0bux6tbhn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82d42qko7b0bux6tbhn3.png" alt="Showing the console logs of our script, where we can see the path and the markdown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yay, that worked! And honestly, we could leave it there if you don't mind typing commands in the terminal. We don't need vscode for any of this really, we could let ts-node do our type-checking.&lt;/p&gt;

&lt;p&gt;But we don't &lt;em&gt;want&lt;/em&gt; to do our own command line instructions now do we? We want to AUTOMATE. And particularly, I want VSCode to do the work for me!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2 - Tasks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/CCKYPqiFptOLGfjGms/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/CCKYPqiFptOLGfjGms/giphy.gif" alt="Manager saying to office worker, "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start with, I'm going to pull a line of text straight from the &lt;a href="https://code.visualstudio.com/docs/editor/tasks" rel="noopener noreferrer"&gt;VSCode documentation&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;"Tasks in VS Code can be configured to run scripts and start processes so that many of these existing tools can be used from within VS Code without having to enter a command line or write new code."&lt;/p&gt;

&lt;p&gt;Great, that looks like exactly what we want.&lt;/p&gt;

&lt;p&gt;"Workspace or folder specific tasks are configured from the tasks.json file in the .vscode folder for a workspace."&lt;/p&gt;

&lt;p&gt;Say less, fam.&lt;/p&gt;

&lt;p&gt;Jokes aside, this is exactly what we're going to do next, making a &lt;code&gt;.vscode&lt;/code&gt; folder in our project and adding a &lt;code&gt;tasks.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux3hj3cwwy0u977z4ljk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux3hj3cwwy0u977z4ljk.png" alt="Image showing updated project folders with a .vscode folder containing a tasks.json file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://code.visualstudio.com/docs/editor/tasks#_examples-of-tasks-in-action" rel="noopener noreferrer"&gt;tasks API&lt;/a&gt; is pretty robust, coming with a suite of built-in variables, integrations for common operations like build-time and run-time actions, and pre-existing hooks and plug-ins, but for our needs we just need a small custom task ourselves.&lt;/p&gt;

&lt;p&gt;Here is the json that we will add to out tasks.json file to tell VSCode how to execute our little ts-node script.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CreateDay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ts-node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"./createBujoTemplate.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"${cwd}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"${input:date}"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"promptString"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Date for your new template. Preferred format yyyy-mm-dd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;I'm going to try my best to step through the various parts of this json.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we declare the task version we're working with. At the time of writing, 2.0.0 is the default. &lt;/li&gt;
&lt;li&gt;Then we make a &lt;code&gt;tasks&lt;/code&gt; field; a list of the all the tasks we would like VSCode to use. We currently have the one.&lt;/li&gt;
&lt;li&gt;In that task, we specify the task type (shell or process), the tasks &lt;em&gt;unique&lt;/em&gt; label (it will yell if you give two tasks the same label), and a way to specify the main command, and any arguments it needs. &lt;/li&gt;
&lt;li&gt;Note "${cwd}" as our third argument. CWD (which stands for current working directory) is a built in variable VSCode makes available for use in writing tasks.&lt;/li&gt;
&lt;li&gt;Below that, we define another variable &lt;code&gt;"${input:date}"&lt;/code&gt;, which makes use of VSCode's ability to define custom input variables that need to be provided by the user.&lt;/li&gt;
&lt;li&gt;After our task list, we define our list of inputs, where we specify an input we call date.&lt;/li&gt;
&lt;li&gt;The type &lt;code&gt;promptString&lt;/code&gt; is a VSCode definition that just means the user needs to provide some string of text. There's options for providing a list or dropdown or even other commands. We're just using a string.&lt;/li&gt;
&lt;li&gt;Finally, we add a description and a default value for our input.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;And with that all in place, we should be be hit &lt;code&gt;Cmd-Shift-P&lt;/code&gt; (or &lt;code&gt;Cntl-Shift-P&lt;/code&gt; on Windows Systems) to bring up the &lt;a href="https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette" rel="noopener noreferrer"&gt;Command Palette&lt;/a&gt; and find the &lt;code&gt;Run Task&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;That will open up a dropdown showing available tasks where we find our newly added custom task &lt;code&gt;CreateTemplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Selecting &lt;em&gt;that&lt;/em&gt; takes us to a prompt asking if we need any specific debugging environment while running the script; we can just click &lt;code&gt;continue without scanning output&lt;/code&gt; for now.&lt;/p&gt;

&lt;p&gt;Finally, we get a prompt asking for that input we defined earlier!&lt;/p&gt;

&lt;p&gt;With all that in place, we can watch as the terminal details the running of our code.&lt;/p&gt;

&lt;p&gt;And if we check the file system...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7f0dmwywzjxw42t9trv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7f0dmwywzjxw42t9trv.png" alt="Showing our full vscode setup, and the file that was just created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We did it!&lt;/p&gt;

&lt;h2&gt;
  
  
  To Sum Up
&lt;/h2&gt;

&lt;p&gt;So just to recap, we originally had a very manual process, that required us to create and populate a file with the same information every day. And now we've reduced all those to a few keystrokes! I know this doesn't feel like a lot, in terms of the complexity of the code we automated away, but we've barely scratched the surface of what tasks are capable of here. We could've set this task to run whenever we opened our project, or connected it to a cron job or a Github action.&lt;/p&gt;

&lt;p&gt;Not everything should be automated, but it's worth considering what could be automated, and if it's your goal to get this kind of behaviour, hopefully this article let you realise it's not as far away as you might think. Give it a try.&lt;/p&gt;

&lt;p&gt;Build your own tools sometimes, not because you have to, but because you want to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v4Nmigh6iwJwK5yfrT/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v4Nmigh6iwJwK5yfrT/giphy.gif" alt="Image of Jeanine from the tv show Abbott Elementary saying "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>vscode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Revealing Compound Types in Typescript</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Thu, 10 Nov 2022 16:40:30 +0000</pubDate>
      <link>https://forem.com/kirkcodes/revealing-compound-types-in-typescript-2ic8</link>
      <guid>https://forem.com/kirkcodes/revealing-compound-types-in-typescript-2ic8</guid>
      <description>&lt;p&gt;In this post I would like to show a small generic type I use sometimes when writing Typescript to improve intellisense and my developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Frequently when writing &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt;, I run into the following scenario:&lt;/p&gt;

&lt;p&gt;I have a set of types that I sometimes use separately or in combination depending on the context. I make heavy use of &lt;a href="https://code.visualstudio.com/docs/editor/intellisense" rel="noopener noreferrer"&gt;intellisense&lt;/a&gt; in my IDE to get information about the shape of data structures as I write.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// our representative for some application user object&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// github data for our app users&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GithubUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// a certain set of functions only care about core user data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// and others are concerned with finding and revealing github data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchGithubUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;GithubUser&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We have a &lt;code&gt;User&lt;/code&gt; and a &lt;code&gt;GithubUser&lt;/code&gt; type that both have different interfaces and their own methods for fetching and processing from their respective APIs. However, there are times in my UI when they need to be combined into a single entity&lt;/p&gt;

&lt;p&gt;With both of these separately, intellisense can give us an idea of the shape of the data structure we can expect to see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2qehs7e8i35fu5ex7hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2qehs7e8i35fu5ex7hw.png" alt="Intellisense for our Github User data type that appears when we hover over the type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if we try to make a type that combines the two, using &lt;a href="https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types" rel="noopener noreferrer"&gt;Typescript's (&amp;amp;) intersection syntax&lt;/a&gt;, we find that the intellisense now only shows use the type names, and will no longer reveal their shapes to us.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UnifiedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;GithubUser&lt;/span&gt;

&lt;span class="c1"&gt;// code where I need a unified object containing info from both&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displayUserdata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnifiedUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifwe2imirhhabt0l6zs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifwe2imirhhabt0l6zs5.png" alt="Image highlighting the intellisense for our UnifiedUser type and how it just shows User and Github user but not their details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By combining multiple types, we've obscured their implementations. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;The solution here, is to use a small bit of Typescript's very advanced &lt;a href="https://www.typescriptlang.org/docs/handbook/2/types-from-types.html" rel="noopener noreferrer"&gt;type manipulation&lt;/a&gt; abilities to re-expose the shape of our objects. We can do this using a combination of two concepts, &lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html" rel="noopener noreferrer"&gt;mapped types&lt;/a&gt;, and &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;Generics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rather than go headlong into the full explanation of the solution, I'll present it first, and discuss how the pattern works after.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Spread&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UnifiedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Spread&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;GithubUser&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we've made a small generic type which I've called &lt;code&gt;Spread&lt;/code&gt; (there may be an better name for this), which we can pass our intersection of &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;GithubUser&lt;/code&gt;, and we find that we can now see the object representing the combination of the two types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk8ypv4v9xtltim5ukrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk8ypv4v9xtltim5ukrw.png" alt="Image showing how our Spread generic type reveals all the fields of User and GithubUser combined"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Without getting too much into the weeds of the immensely deep, and admittedly, arcane syntax of the Typescript type system, what we've essentially done here is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The type &lt;code&gt;Spread&lt;/code&gt; is parametrized, meaning it itself accepts a type as part of its implementation, similar to how a function accepts a variable to use to figure out its result. It's a type who's value depends on another type!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We've called that type variable that goes into &lt;code&gt;Spread&lt;/code&gt;, &lt;code&gt;Type&lt;/code&gt;. Sometimes people use &lt;code&gt;T&lt;/code&gt; or some other generic name. Like regular variables, you can call type variables anything that isn't an existing type or keyword.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After the equal sign, in the type body we define an object whose fields are the keys of the incoming type variable, and who's values are the values associated with those fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;[Key in keyof Type]&lt;/code&gt; syntax makes another type variable, &lt;code&gt;Key&lt;/code&gt; that represents all the keys (fields) of the type passed in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And finally, &lt;code&gt;T[Key]&lt;/code&gt;, passes our key variable into our type variable, to get the value associated with that key! Just like how you would say &lt;code&gt;SomeObject['somefield']&lt;/code&gt; in a real JS object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This essentially maps the keys and values of the &lt;em&gt;entire&lt;/em&gt; intersection into a object containing both.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The intellisense sees this new object now, and not the original types used to make the intersection.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Unions
&lt;/h2&gt;

&lt;p&gt;One nice thing about this pattern is that it works for &lt;a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#unions" rel="noopener noreferrer"&gt;unions&lt;/a&gt; as well.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Arrows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Up&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Down&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Left&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Right&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Pressables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Arrows&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Buttons&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SpreadPressables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Spread&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Arrows&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Buttons&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Pressables&lt;/code&gt; suffers from the same problem as our object intersection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F671onnikzzllwxo79hw8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F671onnikzzllwxo79hw8.png" alt="A type pressable that is the union of two unions, hiding their imprementations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;SpreadPressables&lt;/code&gt; does not!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1e3sgrnr02zwten7ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1e3sgrnr02zwten7ju.png" alt="SpreadPressable type intellisense exposing all the values of the two unions that made it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;While this patterns works really well with these two use cases, it can become a little wonky otherwise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One notable caveat is this solution doesn't work recursively. If a field in the intersection is itself some object, this won't expose that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mixing unions and intersections can also sometimes fail to spread out in a way that feels intuitive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;If the above statements don't immediately click, that's fine! Understanding and Implementing these helper types isn't trivial, which is why Typescript provides a whole suite of &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#handbook-content" rel="noopener noreferrer"&gt;Utility types&lt;/a&gt; which have useful built-ins for common transformations that people tend to use when working with TS/JS applications.&lt;/p&gt;

&lt;p&gt;Also, there are many occasions where we &lt;em&gt;want&lt;/em&gt; the implementation details of types to be squashed, especially when designing APIs. Once Typescript does expose type info, it is extremely difficult to keep it hidden if it exists in the same file. There are more advanced Type-level data structures called &lt;a href="https://calebmer.com/tangents/opaque-types-in-typescript.html" rel="noopener noreferrer"&gt;Opaque types&lt;/a&gt; that do just that, but opaque types go far beyond intellisense; they prevent the consumer from even &lt;em&gt;making&lt;/em&gt; an implementation of the type.&lt;/p&gt;

&lt;p&gt;There may be techniques to expand the utility of this pattern to cover for more use cases, but that's for another time. This post was just to highlight a small scenario that the utility types didn't have an answer for, but the solution turned out to be quite close at hand with some type-level programming!&lt;/p&gt;

&lt;p&gt;Here's a link to a &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAqgzhATlAvFA3gKClAdgQwFsIAuKOYRAS1wHNsp9bS8BXQgIyUwF9NNQkKACUIYAPZwqwcYhCoMDAsTIVqdBq0QAbVZRr0+A8NADi0gBasO8JAqw4qAEzK52XRA0RjJZURKkZOQBtAF1efkFoADFWbW1bZDREqAAyKHNgKxsET2MhAGUwb3wnAB4AFRMAPnsoYIBpCHkaKABrZvEAMygqyFCyPohG5tCoHihIkygAQW1gWPiUtCKS8pT0zOzE6v4AY3FcCignKjgwbXwQRKd8YHwFAApb+7I5hbiE3IBKVFqHKAAekBUAAdODyOJiIw9sAqIc4JMjAcjsAoF0IMA9hZllBHt8yMt-gxgWDwV5MVpcBg8EQWAByekAGkYzDIAE5xvxkQi0RisRYttZcfiyEKcnYUMScKTwaCKcAqTTvAEyGEWc4OVzeEA" rel="noopener noreferrer"&gt;typescript playground&lt;/a&gt; where you can see all the code written here in it's entirety.&lt;/p&gt;

&lt;p&gt;Thanks for reading :)&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>generic</category>
    </item>
    <item>
      <title>Semantics, Not Syntax; Developer empowerment using functional-first programming</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Mon, 29 Nov 2021 16:35:42 +0000</pubDate>
      <link>https://forem.com/kirkcodes/semantics-not-syntax-developer-empowerment-using-functional-first-programming-45oo</link>
      <guid>https://forem.com/kirkcodes/semantics-not-syntax-developer-empowerment-using-functional-first-programming-45oo</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;"It's not about syntax; it's about semantics."&lt;/em&gt; - &lt;a href="https://twitter.com/rtfeldman" rel="noopener noreferrer"&gt;Richard Feldman&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is just a collection of my thoughts concerning my favourite languages and why I enjoy them. For the most part, I think software developers operate like artists; our attachment or reluctance to different technologies is heavily influenced by recency, emotional connection, and personal association. We like the things we like, not necessarily the things that are "correct" if there is even some correct to be.&lt;/p&gt;

&lt;p&gt;However, in recent times I've seen a few languages spark joy for myself and other developers, and I have spent some time contemplating why that is the case; what makes these (seemingly disparate and unrelated) languages all seem to inspire the same type of zeal and interest in their users.&lt;/p&gt;

&lt;p&gt;That seeming disparity is essential. Rust, Elixir, f#, and Go could never be mistaken for each other, yet their advocates' &lt;em&gt;emotional&lt;/em&gt; response feels familiar. And in between the various quirks of function definition, platforms, object definitions, etc., there seems to be some more fantastic design ethic that draws people in.&lt;/p&gt;

&lt;p&gt;So I'd like to surface some of the ones that I've noticed and maybe explain a bit of &lt;em&gt;why&lt;/em&gt; I think they matter to us.&lt;/p&gt;

&lt;p&gt;Note: I'll be using examples from a tiny &lt;a href="https://github.com/tkshill/FSnake/blob/master/src/Snake.fs" rel="noopener noreferrer"&gt;implementation&lt;/a&gt; of the Snake Game I wrote in &lt;a href="https://fsharp.org/" rel="noopener noreferrer"&gt;F#&lt;/a&gt; here because the language exemplifies pretty much all the things I'll be speaking about today. Also, I like it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immutability as Default
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/JSjiaBMFpyrQ66VfdP/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/JSjiaBMFpyrQ66VfdP/giphy.gif" alt="gif about hating changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I had to put forth the single most powerful of these language semantics to influence and improve the type of programs we write, it would have to be the &lt;em&gt;decision&lt;/em&gt; to make variables &lt;strong&gt;not&lt;/strong&gt; alterable by default after initialisation. The concept of explicit mutation seems so fundamentally baked into what programming means that the idea of working without it seems inconceivable. What does it mean to program with it? &lt;/p&gt;

&lt;p&gt;To the computer, not much. Under the hood, languages that leverage immutability are the same variables and spaces in memory that we're used to. But to the developer, it's a &lt;strong&gt;big deal&lt;/strong&gt; to be able to make guarantees that data can only ever be what you defined it to be the &lt;em&gt;first&lt;/em&gt; time. And if you want something new, you can use the first thing as a template for the new thing, but they are not the same.&lt;/p&gt;

&lt;p&gt;Let's look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StructAttribute&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AlreadyOver&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;EatsFood&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;newSnake&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updateSnake&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Snake&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;newFood&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createFood&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Size&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newSnake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;newSnake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newSnake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newFood&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have the core data type for our Snake implementation, the type &lt;code&gt;Game&lt;/code&gt;, a record/object with fields Food of a kind &lt;code&gt;Food&lt;/code&gt;, Snake of type &lt;code&gt;Snake&lt;/code&gt;, Size of type &lt;code&gt;int&lt;/code&gt; and Status of type &lt;code&gt;Status&lt;/code&gt;. We'll learn what those types are a little later in the article, but what I want to focus on right now is a snippet of the &lt;code&gt;advance()&lt;/code&gt; function shown below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;advance()&lt;/code&gt; is a function that accepts a game and returns a game. I've trimmed away most of the implementation but kept the portion where advance has determined the snake has eaten a piece of food.&lt;/p&gt;

&lt;p&gt;Let's look at the order of operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;let newSnake = updateSnake game.Snake true&lt;/code&gt; is used to create a new snake based on the state of the old one.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let newFood = createFood game.Size (newSnake.Head:: newSnake.Tail)&lt;/code&gt; creates a &lt;em&gt;new&lt;/em&gt; piece of food by passing in the size of the grid and our new snake.&lt;/li&gt;
&lt;li&gt;Finally we return &lt;code&gt;{ game with Snake = newSnake; Food = newFood }&lt;/code&gt;. Now, this &lt;em&gt;looks&lt;/em&gt; very much like a stateful update. It is changing the game fields to these new values. But what it's doing is &lt;em&gt;making a new record&lt;/em&gt;, using the values from the old game, but with these new changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old game was unmodified. The game returned is an entirely different value. But &lt;strong&gt;the semantics of the language make it cheap, efficient, and sensible to produce new values.&lt;/strong&gt; So we don't have to worry about actions later accidentally mutating previous values.&lt;/p&gt;

&lt;p&gt;It's essential to think about this last part. It's not that we &lt;em&gt;can't&lt;/em&gt; program like this in other languages. It's just that their semantics make it less worthwhile. It's harder to track when you're mutating or not. Idiomatic methods and functions in those languages mutate. There could be a performance overhead for making new values too often. These are all &lt;em&gt;semantic barriers&lt;/em&gt; to using immutable values and disempowering the developer from this programming style, leading to more precarious code.&lt;/p&gt;

&lt;p&gt;In languages like F# and &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;, the &lt;code&gt;mutable&lt;/code&gt; keyword is an intentional indicator to the language that you intend to modify a value. In languages like &lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;Elm&lt;/a&gt;, you cannot do mutation at all. But either way, it makes the programmer much more &lt;em&gt;thoughtful&lt;/em&gt; about how they change states in their code. And in the field of software development, &lt;strong&gt;thoughtfulness matters&lt;/strong&gt;*.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Default Nulls
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/ZCCERtxEH01ksB2tXu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ZCCERtxEH01ksB2tXu/giphy.gif" alt="gif of being disappointed by nothing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I won't spend too much time on this one since many, many people have expounded on the &lt;a href="https://hinchman-amanda.medium.com/null-pointer-references-the-billion-dollar-mistake-1e616534d485" rel="noopener noreferrer"&gt;dangers&lt;/a&gt; of &lt;a href="https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/" rel="noopener noreferrer"&gt;null&lt;/a&gt; &lt;a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/" rel="noopener noreferrer"&gt;values&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Suffice to say, it is difficult to &lt;strong&gt;trust&lt;/strong&gt; types, typing, and functions itself in languages that do not or cannot guarantee that the function will return the type you expect, and perhaps more importantly, do not enforce that you write operations that &lt;em&gt;return&lt;/em&gt; the types you say they do.&lt;/p&gt;

&lt;p&gt;It's OK to have a function that returns &lt;code&gt;Some value&lt;/code&gt; or &lt;code&gt;Nothing&lt;/code&gt;. That's a semantically correct logical operation. Sometimes things fail. What's &lt;strong&gt;not&lt;/strong&gt; fine is if language &lt;em&gt;inserts&lt;/em&gt; a null value because you &lt;em&gt;forgot&lt;/em&gt; to return a value at all operation paths in your function. It's hard to write and use code that you cannot trust. It's hard to read and follow docs if every function can &lt;em&gt;not&lt;/em&gt; return the value it's supposed to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;changeDirection&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="n"&gt;proposedChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;proposedChange&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Perpendicular&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Snake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Snake&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;proposedChange&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function, &lt;code&gt;changeDirection&lt;/code&gt;, is responsible for changing the way the snake is moving. It has some guard logic for making sure the snake's direction can only change &lt;em&gt;perpendicularly&lt;/em&gt;. A snake moving up can either go left or right, but it can't, for example, reverse back into itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;| _ -&amp;gt; game&lt;/code&gt; is the default case for our match (switch) statement where we return the game that came in unchanged. And F# will complain if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We forget the default (or fail to account for all possible shapes of the input)&lt;/li&gt;
&lt;li&gt;We return anything but a game from this function at any point. It won't compile unless we &lt;em&gt;tell&lt;/em&gt; it that this function could return a game or something else. But then, everywhere we call this function, we would have to deal with the fact that it &lt;em&gt;might&lt;/em&gt; return a game or it might not. All our inputs have to match our outputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that means if I say a function returns an &lt;code&gt;int&lt;/code&gt;, the language itself will ensure I'm not lying, and I'd rather not be a liar.&lt;/p&gt;

&lt;p&gt;Almost every language I know created in the last decade does not have default nullability on its functions and objects. What was meant as a convenience turned out to be a detriment, and it turns out developers prefer living without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brevity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/X9jbyxzhco1JmR2AsR/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/X9jbyxzhco1JmR2AsR/giphy.gif" alt="gif of a short person being annoyed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have &lt;em&gt;many&lt;/em&gt; thoughts on brevity. So many thoughts. I can't write them all because there's something wrong with not being brief about being brief.&lt;/p&gt;

&lt;p&gt;So, briefly,&lt;/p&gt;

&lt;p&gt;Programming languages and paradigm popularity ebbs and wanes. But nothing truly goes away. In the 90s and aughts, we saw C#, C++, and Java in maybe their heyday as the language &lt;em&gt;du jour&lt;/em&gt; of software development. Many times, it has been posited that the rise of &lt;em&gt;dynamic&lt;/em&gt; languages like python, ruby, and javascript was a direct response to developers feeling the friction of the overhead of the enterprise languages.&lt;/p&gt;

&lt;p&gt;Some people think that this was a resistance to the rigidity of static typing. Developers wanted more freedom and spent less time "type wrangling", opting for performing actions over defining structures.&lt;/p&gt;

&lt;p&gt;I think that's &lt;em&gt;part&lt;/em&gt; of it, and not all of it. Specifically, I don't believe the types were necessarily the problem, but more like collateral damage from incredibly verbose language syntax.&lt;/p&gt;

&lt;p&gt;Curly braces, accessibility modifiers, semicolon, semicolon, semicolon, and always everywhere type definitions made for an intimidating syntax for new developers and seemed to add to laden the burgeoning developer; the better you understood the language, the more code you seemed to have to write to express yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;opposite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;// Direction -&amp;gt; Direction&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Up&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Down&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Down&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Up&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Right&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Right&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a private function in F# that returns the opposite direction. F# does not make explicit return statements in its functions; everything is an expression, so the function's body is a valid return. Indentation handles defining the boundaries of the function body. Newlines define the following case in the switch. Arrows (-&amp;gt;) separate cases from results. &lt;em&gt;Mise en place&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Languages like python, F#, and Rust, in contrast to the older iterations of the enterprise languages, do their best to eliminate superfluous syntax, verbose symbols and overly elaborate exposition for every construct. They embrace whitespace as syntax; an idea which arguably does not make that much sense for compilation, but makes a massive difference for &lt;strong&gt;human readability&lt;/strong&gt;. Code people can read and parse is lexically succinct.&lt;/p&gt;

&lt;p&gt;By and large, languages are getting briefer and more expressive, relying more on intuitive whitespace for scoping.&lt;/p&gt;

&lt;p&gt;And as for the question of verbose type definitions:&lt;/p&gt;

&lt;h2&gt;
  
  
  Type inference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hTerI4FpPtJg4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hTerI4FpPtJg4/giphy.gif" alt="gif of two men asking if you're psychic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a direct continuation of the pattern of brevity discussed above, recently we've seen the emergence of &lt;strong&gt;type inference&lt;/strong&gt; (the ability for a language compiler or runtime to determine and &lt;em&gt;enforce&lt;/em&gt; types based on usage).&lt;/p&gt;

&lt;p&gt;All the F# code I've shown you so far has been fully/strongly typed. Every function parameter and function return has been deduced and enforced by the type checker.&lt;/p&gt;

&lt;p&gt;Some tools, like the VSCode &lt;a href="https://ionide.io/" rel="noopener noreferrer"&gt;Ionide&lt;/a&gt; extension take advantage of this and will display the types &lt;strong&gt;for you&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmzeapno1rna3250q19fs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmzeapno1rna3250q19fs.png" alt="image of the code with type hints"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the type comments you see here are overlaid on to the code. They're not actually being written in the file.&lt;/p&gt;

&lt;p&gt;It's hard for me to return to dynamic languages when I know I can get all the benefits of strong types and compile time guarantees without having to explicitly write all the type information.&lt;/p&gt;

&lt;p&gt;Safety meets brevity. Admittedly, type inference isn't perfect, and you lose context if you're reading the code outside of an optimized editor experience, but at that point, it's still no &lt;strong&gt;worse&lt;/strong&gt; than if the code was dynamic, and you still have the knowledge that all the logic is type safe and checks out.&lt;/p&gt;

&lt;p&gt;I never personally felt the slow down that dynamic programming enthusiasts have mentioned comes with using static types - I think I write &lt;strong&gt;working&lt;/strong&gt; code faster with strong typing - but if you are concerned with speed and expressiveness, type inference seems like an excellent way to mitigate it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Abstract Data Types
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/krtDmVuQGssOtMWfRg/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/krtDmVuQGssOtMWfRg/giphy.gif" alt="gif of being impressed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've reached the final pattern I want to discuss here and I feel like I've saved the best for last; at least for me, it is my personal favourite of all the things we've discussed here and the one that has had the greatest impact on my progression as a developer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guide.elm-lang.org/types/custom_types.html" rel="noopener noreferrer"&gt;Algebraic Data Types&lt;/a&gt; aka Custom Types aka Union and Product Types are a relatively straightforward concept with profound applications.&lt;/p&gt;

&lt;p&gt;Ultimately, programming is giving instructions to a machine to perform meaningful work. And &lt;strong&gt;modern programming involves &lt;em&gt;making abstractions&lt;/em&gt; that produce maintainable code that performs the behaviours we desire.&lt;/strong&gt; Values, functions, classes, modules and all these other namespaces allow us to define constructs and ideas that map the &lt;em&gt;real&lt;/em&gt; domain of our endeavours to a program space of data structures and logic.&lt;/p&gt;

&lt;p&gt;Algebraic Data Structures (ADTs) provide a straightforward syntax for expressing the shape of a problem with as little overhead as possible.&lt;/p&gt;

&lt;p&gt;Let's see how.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Snake&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Head&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Tail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Food&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Active&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Won&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Lost&lt;/span&gt;

&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Up&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Down&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the types representing the domain of my Snake game. The concepts, so to speak, that are meaningful to the idea of snake. What &lt;em&gt;is&lt;/em&gt; a game of snake? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the minimum amount of information necessary to play a game of snake?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are a few interesting things happening here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data structure for the game is composed from smaller structures&lt;/li&gt;
&lt;li&gt;We can easily alias types (give them a more semantically meaningful name that's relevant on the context of our application). Like how &lt;code&gt;Food&lt;/code&gt; and the snake's &lt;code&gt;Head&lt;/code&gt; are both just positions, but we can use their aliases throughout our code for more clarity.&lt;/li&gt;
&lt;li&gt;Status and Direction are both &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html" rel="noopener noreferrer"&gt;Union types&lt;/a&gt;. They're similar to enums, but they're not integers or strings under the hood. They're fully qualified Values that we can use in our code, like making our own primitives unique to this application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might not find this particularly exciting, saying these are &lt;em&gt;just&lt;/em&gt; fancy enums and records, but ADTs are fully unencumbered by shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Restart&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Dir&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tick&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we make a &lt;code&gt;Message&lt;/code&gt; type that has two simpler values, &lt;code&gt;Restart&lt;/code&gt; and &lt;code&gt;Tick&lt;/code&gt; that don't rely on any other data, and one parametrized value, &lt;code&gt;Dir&lt;/code&gt; that requires a &lt;code&gt;Direction&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Restart&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Dir&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changeDirection&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tick&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we consume this data type we can make decisions and access the associated data with each value, but &lt;strong&gt;not&lt;/strong&gt; mix them up. We can't use the direction in any case except the &lt;code&gt;Dir direction&lt;/code&gt; case, because directions only exist on that value.&lt;/p&gt;

&lt;p&gt;This allows us to &lt;em&gt;precisely&lt;/em&gt; model domains without wastage. It is not a trivial operation to express something like that message type in a language like Java, and requires significantly more code to do so. As a consequence, people rarely do it, opting to use more mutation, and nullable values to handle states where data is lacking, or shouldn't exist.&lt;/p&gt;

&lt;p&gt;And that causes more bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We shouldn't write code that squeezes our real-world domain into the primitive types of our programming languages; our programming languages should provide the tools to represent our domain precisely and without wastage.&lt;/strong&gt; The better the representation, the easier it will be to work with the data.&lt;/p&gt;

&lt;p&gt;ADTs are now a first-class feature for me in any language I want to use. The more resistance a language gives me to describing what a thing &lt;em&gt;actually&lt;/em&gt; is, the less I find myself wanting to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;If you've made it here, thank you for taking the time to read my little love letter to the patterns I enjoy, and why I think other developers enjoy them as well.&lt;/p&gt;

&lt;p&gt;We've gone this whole way without me mentioning functional programming, and that's deliberate. While almost all of these patterns saw their origins and notable iterations in the functional programming space, I've recently found myself moving away from attempting to separate the world into functional or not functional; I'd rather talk about patterns that I like, and tools that implement them.&lt;/p&gt;

&lt;p&gt;F# itself has recently done the same with it's updated tagline:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;F# empowers everyone to write succinct, robust and performant code&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The goal is not to be functional or object oriented. It's not to be the most popular language or the fastest language.&lt;/p&gt;

&lt;p&gt;It's to help people write good code.&lt;br&gt;
It's to help developers express their desires.&lt;br&gt;
It's to avoid bugs, and errors.&lt;/p&gt;

&lt;p&gt;Languages that execute well on these ideas, seem to be well received. And it's not just the new languages. All the older tools and frameworks are thinking about developer empowerment. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was never really about semicolons.&lt;/strong&gt; The things we've just talked about aren't recommendations or suggestions in style guides. They're not buried in tomes like, "Everything you need to know about X". They're baked into the language ecosystems themselves.&lt;/p&gt;

&lt;p&gt;Let me know in the comments what you think, and what language patterns bring you delight.&lt;/p&gt;

</description>
      <category>fsharp</category>
      <category>functional</category>
      <category>typescript</category>
      <category>rust</category>
    </item>
    <item>
      <title>Talking technique: Recognizing context for cleaner design</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Wed, 17 Nov 2021 12:33:17 +0000</pubDate>
      <link>https://forem.com/kirkcodes/talking-technique-recognizing-context-for-cleaner-design-32o1</link>
      <guid>https://forem.com/kirkcodes/talking-technique-recognizing-context-for-cleaner-design-32o1</guid>
      <description>&lt;h2&gt;
  
  
  A Short Introduction
&lt;/h2&gt;

&lt;p&gt;This is a short post covering a relatively useful pattern for writing functions that I have found very applicable to anyone writing modern software. The pattern itself isn't particularly arcane, and many developers find themselves adopting this style with time.&lt;/p&gt;

&lt;p&gt;However, I've found that sometimes, speaking about something explicitly can accelerate learning and understanding faster than trying to intuit things over time. I remember being fairly excited once I noticed the pattern and grateful that once I brought it up, someone more senior than myself took the time to break it down.&lt;/p&gt;

&lt;p&gt;So let's see if I can pass it on.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's the pattern
&lt;/h2&gt;

&lt;p&gt;Sometimes, I feel like the best way to approach things is to lay an elaborate groundwork of pieces and slowly assemble the puzzle together with the reader. But this time, I think it's best to start with the final statement, so let's just start with defining the pattern itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"User-defined functions should try not to consume "container" data structures.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Those data structures should be manipulated at a higher level by built-in features of the language itself."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the above statement doesn't immediately click, that's okay! That's what this article is for. Since we'll be looking at examples in Javascript, I also have a more specific version of the statement for js development, which goes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"User-defined functions should try not to consume Arrays, Promises, and Nullables. Those should be manipulated by the built-in methods of their respective libraries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User-defined functions should try to concern themselves with the values inside the container data structures instead."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Still unclear? That's fine. Let's examine this more in-depth with some examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example one: Manipulating the elements in an array.
&lt;/h2&gt;

&lt;p&gt;Let's take a look at the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;radii&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sphericalVolumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;volumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="nx"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;volumes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sphericalVolumes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// [4.1887902047863905, 268.082573106329, 1436.7550402417319, 4188.790204786391, 9202.7720799157]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've created this function, &lt;code&gt;sphericalVolume()&lt;/code&gt;, that accepts a list of "radii" (radiuses? I don't honestly know) and calculates the Volume of the corresponding sphere. This function is &lt;em&gt;fine&lt;/em&gt;, but there are a few things we could critique here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By having the function consume an array, and by using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"&gt;forEach()&lt;/a&gt;, we've bound it to always consuming an array-like structure. If we ever decide to use a different container for our radiuses (like a list or a set), this will break.&lt;/li&gt;
&lt;li&gt;Consuming a list also makes our tests more complicated. In addition to checking the &lt;em&gt;actual&lt;/em&gt; calculation of the spheres, we now have to also ensure this maintains the right behaviour when the list is empty or contains non-numerical values. Neither of which has anything to do with the function's true purpose; &lt;strong&gt;calculating a volume from a radius&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Another added complexity of the tests is that the value returned is now an array that must be unpacked to retrieve the value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's compare it to this refactored version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;radii&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sphericalVolume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sphericalVolume&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// [4.1887902047863905, 268.082573106329, 1436.7550402417319, 4188.790204786391, 9202.7720799157]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we leverage the fact that arrays &lt;em&gt;already&lt;/em&gt; have the tools to transform values in that container. We can do away with most of the trimming around that original function with the built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"&gt;map()&lt;/a&gt; method, and most importantly, &lt;em&gt;our custom function accepts and returns a single value now.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Testing this function is way easier than before because it always gets a number and returns a number. In Javascript, we can't guarantee it will be &lt;em&gt;passed in&lt;/em&gt; a number (in Typescript, we can), but if it does get passed in something else, that's not its job to guarantee.&lt;/p&gt;

&lt;p&gt;Although this article isn't explicitly about &lt;a href="https://medium.com/@vcarl/overly-defensive-programming-e7a1b3d234c2"&gt;overly defensive coding&lt;/a&gt;, this pattern does help you avoid it. As a rule of thumb,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;functions should not both &lt;em&gt;validate&lt;/em&gt; an incoming input &lt;em&gt;and&lt;/em&gt; perform an operation.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;It is the &lt;em&gt;caller's&lt;/em&gt; job to ensure the values it passes to the function are correct.&lt;/p&gt;

&lt;p&gt;Let's see that more clearly in another example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Two: Manipulating a value that may be null or undefined
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;samplePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Justin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Belieber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;samplePerson&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,`&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Valued Customer,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;77&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;makeGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;makeGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// "Hello Dr Justin Belieber,"&lt;/span&gt;
&lt;span class="c1"&gt;// "Hello Valued Customer," &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here we have a mock of doing some kind of data retrieval from an array. This array is supposed to contain objects with information about people's names and titles, identifiable by a unique id. We use the &lt;code&gt;find()&lt;/code&gt; method to get the objects, but &lt;code&gt;find()&lt;/code&gt; will return &lt;code&gt;undefined&lt;/code&gt; if it fails to find a matching element of the array. Our &lt;code&gt;makeGreeting()&lt;/code&gt; function receives this value, checks if it isn't undefined, and returns either a custom, or generic message accordingly.&lt;/p&gt;

&lt;p&gt;You can probably already see the problem here, but let's look at a potential alternative.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;samplePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Justin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Belieber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;samplePerson&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;possible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;possible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;makeGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;possible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Valued Customer,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// "Hello Dr Justin Belieber,"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here again, we've done what we did in the first example. We've moved the validation &lt;em&gt;out&lt;/em&gt; of the function and now ensured that it only ever has to deal with real concrete values.&lt;/p&gt;

&lt;p&gt;Thanks to things like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator"&gt;ternary&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator"&gt;nullish coalescing&lt;/a&gt; operator, we can handle logic concerning whether a value exists using native language features without concerning the custom function.&lt;/p&gt;

&lt;p&gt;This gives us similar testing, readability, and refactoring advantages as we did before.&lt;/p&gt;

&lt;p&gt;Now you might have noticed, earlier in the article, I referred to these data structures as "container" structures. But container may not be the best term to describe something like a value that may be null. Another way we can describe these are values &lt;em&gt;in context:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the values in the first example have the context of being held inside an array&lt;/li&gt;
&lt;li&gt;the values in the second example have the context of &lt;strong&gt;maybe not existing&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phrased like that, it might seem a little more obvious why it's so much easier to write and manipulate functions that work with values that &lt;em&gt;exist&lt;/em&gt; and are usable, rather than ones that we aren't sure about.&lt;/p&gt;

&lt;p&gt;To wrap up, let's look at just one more example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Three: Handling Promises
&lt;/h2&gt;

&lt;p&gt;This last example will be the most lengthy, but I promise it's just a continuation of the same patterns we've seen so far. It just requires a bit more preamble to make sense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;processResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sprites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sprites&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;front_default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pokeDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pokedex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;899&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://pokeapi.co/api/v2/pokemon/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;processResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spriteDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDivs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;spriteDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;addChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nameDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spriteDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;typeDivs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what's going on here?&lt;/p&gt;

&lt;p&gt;This is a snippet of part of the logic for my Pokedex New Tab Chrome Extension project (really rolls off the tongue right).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;fetch&lt;/a&gt; to request some data from the &lt;a href="https://pokeapi.co/"&gt;pokemon api&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We make a function, &lt;code&gt;processResponse()&lt;/code&gt; that accepts the results of that fetch, checks whether it was successful, and then extracts the relevant data, and then returns that transformed data, or null&lt;/li&gt;
&lt;li&gt;Back in the calling function, we update our html with the relevant poke-info if data returned has a meaningful value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once again, with &lt;code&gt;processResponse()&lt;/code&gt; we've got a function that's attempting to both make sense of some context, &lt;em&gt;and&lt;/em&gt; manipulate the objects inside it.&lt;/p&gt;

&lt;p&gt;Also, because it sometimes returns null, we have to validate &lt;em&gt;again&lt;/em&gt; in the main function on the data returned. Does null even make sense as a return value here? Should it perhaps be an error? This whole thing feels a little too unwieldy for a simple data fetch. &lt;/p&gt;

&lt;p&gt;Can we leverage existing tools in the language to handle some of this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;processResponse2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sprites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sprites&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;front_default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pokeDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pokedex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;899&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://pokeapi.co/api/v2/pokemon/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;processResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spriteDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDivs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;types_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nx"&gt;spriteDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;addChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nameDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spriteDiv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;typeDivs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what's going on in &lt;em&gt;this version&lt;/em&gt; of our logic? Well now, we're leveraging the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"&gt;then()&lt;/a&gt; method on our promise object to pass the value that we want, the object from the successful response.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;processResponse()&lt;/code&gt; therefore no longer has to concern itself with whether the response succeeded; it's a function that is only there for &lt;em&gt;when a success&lt;/em&gt; happens. The ambiguity of our logic goes away, and we even get to use the &lt;code&gt;catch()&lt;/code&gt; method to handle errors any way we choose.&lt;/p&gt;

&lt;p&gt;Cleaner code that easier to reason about, extend, and manipulate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I hope this little foray into code design was useful to you. This is a broad and deep space, and I wish I had more time to present a more substantial mapping of the principles behind these tactics, and how to build upon them. Hopefully this article and others like it can spark interest and thought in the craft of good code, and what the goals are when refactoring.&lt;/p&gt;

&lt;p&gt;"Values in context" are the type of thing where once you notice them, you start seeing them everywhere, because they are everywhere. Knowing when we need to manipulate an array vs just transforming the values inside seems small, but it's the type of thing that can make the difference between spaghetti logic and functions that are easy to reason about.  &lt;/p&gt;

&lt;p&gt;As always, please reach out if you have any questions, comments, or feedback. &lt;/p&gt;

&lt;p&gt;I hope this was valuable for you. Thank you for your time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you want to approach this from a more academic standpoint, the entire class of &lt;em&gt;"contexts that contain a value"&lt;/em&gt; that we've looked at here are referred to as &lt;a href="https://en.wikipedia.org/wiki/Functor_(functional_programming)"&gt;Functors&lt;/a&gt;. There's a &lt;em&gt;very precise&lt;/em&gt; definition of what functors are and how they work but many people just remember them as &lt;em&gt;contexts&lt;/em&gt; that are &lt;strong&gt;mappable&lt;/strong&gt;. &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;then()&lt;/code&gt;, and the ternary operator all do the same thing; they allow us to safely work with a value in some context without disturbing the context itself.&lt;/li&gt;
&lt;li&gt;A note on dogma: Like everything in software these techniques are &lt;em&gt;suggestions&lt;/em&gt; and &lt;strong&gt;not&lt;/strong&gt; absolutes. There are very legitimate reasons for functions to consume arrays and nullables and promises; this was just a way of highlighting that that shouldn't always be the default. For example, a &lt;code&gt;sum&lt;/code&gt; function that &lt;em&gt;is&lt;/em&gt; actually performing a transformation on an entire array, would need that entire area. &lt;/li&gt;
&lt;li&gt;In the first example, you might be tempted to think that the second solution seems better partially because we replaced a more verbose &lt;code&gt;forEach()&lt;/code&gt; with the minimal syntax of &lt;code&gt;map()&lt;/code&gt;, but the solution of &lt;code&gt;map()&lt;/code&gt; in the array consuming version has its own even more subtle flaw.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sphericalVolumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;radii&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code, while having the same issues as its more verbose version, suffers from another potential anti-pattern:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sphericalVolumes()&lt;/code&gt; in this case is just a &lt;em&gt;thin&lt;/em&gt; abstraction over &lt;code&gt;radii.map(radius =&amp;gt; (4 / 3) * Math.PI * radius ** 3)&lt;/code&gt;. So thin, in fact, that you could argue that unless we use this function in multiple places, the abstraction isn't worth hiding the code behind an interface. In other words, wrapping &lt;code&gt;radii.map(radius =&amp;gt; (4 / 3) * Math.PI * radius ** 3)&lt;/code&gt; in &lt;code&gt;sphericalVolumes()&lt;/code&gt; just hides code away that would've been easy enough to understand anyway. The abstraction doesn't help us make sense of the code; it just makes it harder to discover.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>functional</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A Most Magic TicTacToe solution with React and TS</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Tue, 02 Nov 2021 12:13:44 +0000</pubDate>
      <link>https://forem.com/kirkcodes/a-most-magic-tictactoe-solution-with-react-and-ts-4pje</link>
      <guid>https://forem.com/kirkcodes/a-most-magic-tictactoe-solution-with-react-and-ts-4pje</guid>
      <description>&lt;h2&gt;
  
  
  Synopsis
&lt;/h2&gt;

&lt;p&gt;My name is Kirk. I like making small games with code. And today's game is Tic-Tac-Toe. Specifically, this is a post about an alternative algorithm for finding winning combos in Tic-Tac-Toe using a concept called &lt;em&gt;Magic Squares&lt;/em&gt;, but also about burnout, productivity, and finding joy in code. The code is all done in &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt;, and as always, full links and examples will be provided. If you just want to see the final solution, visit the sandbox &lt;a href="https://codesandbox.io/s/github/tkshill/Reac-tac-toe" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Starting from the end with sensible solutions.
&lt;/h2&gt;

&lt;p&gt;Now, normally we'd start a post like this at the beginning; we'd talk about the domain of the physical game, and what elements we'd need in our digital solution. But today we're gonna start at the end; we're gonna take an existing solution and look at what if we just changed a small bit in an interesting way. Like Marvel's &lt;a href="https://www.marvel.com/tv-shows/animation/what-if/1" rel="noopener noreferrer"&gt;What-If&lt;/a&gt;, but with a smaller animation budget.&lt;/p&gt;

&lt;p&gt;So what do we have going on?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ermxwp23zo31qf4yh55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ermxwp23zo31qf4yh55.png" alt="tic tac toe game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My take on Tic-Tac-Toe. Does it work? Yes. A bit plain? Also yes.&lt;/p&gt;

&lt;p&gt;This is our basic Tic-Tac-Toe implementation in React. Each turn a user clicks a cell in the grid, and the game checks to see if they've won.&lt;/p&gt;

&lt;p&gt;Under the hood, our "grid" is just an object whose fields are the numbers of the cells and who's values are "X"s, "O"s, and &lt;code&gt;null&lt;/code&gt;s (for empty cells).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;Grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// this grid would be rendered as the following&lt;/span&gt;

 &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our Tic-Tac-Toe implementation, we need a function that checks whether a player has won after each turn, &lt;code&gt;hasWinner()&lt;/code&gt;. That function can accept a grid and determine if there's a winning set of moves in the grid.&lt;/p&gt;

&lt;p&gt;The win function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winningCombos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// top row&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// middle row&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// bottom row&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// left column&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// middle column&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// right column&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// descending diagonal&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// ascending diagonal&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// map the grid values to the combo keys&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comboValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winningCombos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comboKeys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;comboKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// find returns a value or undefined&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maybeWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;comboValues&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// convert this value to a boolean&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;maybeWinner&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what's happening here?&lt;/p&gt;

&lt;p&gt;First, we create a list of lists representing all the potential winning sequences of cells, all the rows and columns and the two diagonals.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;hasWinner()&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use &lt;code&gt;map()&lt;/code&gt; over our combos to get the grid values for every cell&lt;/li&gt;
&lt;li&gt;Then we use &lt;code&gt;find()&lt;/code&gt; to look for a group which has all X's or all O's&lt;/li&gt;
&lt;li&gt;If we find one, that means there's three of the same value in a row on the board, and we have a winner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/10hexADl3Kl6SY/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/10hexADl3Kl6SY/giphy.gif" alt="it is known gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this &lt;strong&gt;works&lt;/strong&gt; and performs fine. It does the job. But maybe we can do something a bit more fun that does the job. Not with how &lt;code&gt;hasWinner()&lt;/code&gt; works, but with how we get those &lt;code&gt;winningCombos&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here, we basically just wrote them out by hand. And eight wasn't really so bad. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what if we had a 4x4 board?&lt;/strong&gt; That's 10 solutions. And a 5x5 board is twelve. It would be &lt;em&gt;nice&lt;/em&gt; if there was a way to just &lt;em&gt;know&lt;/em&gt; the ways to solve without having to look at the grid and then write them all out.&lt;/p&gt;

&lt;p&gt;And luckily, there just so happens to be a way (or this would be the end of this blog post).&lt;/p&gt;

&lt;p&gt;And that solution, involves &lt;strong&gt;magic squares&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Answers with no questions.
&lt;/h2&gt;

&lt;p&gt;Now, this is meant to be a technical article, but it's worth taking a bit of time to talk about &lt;em&gt;why&lt;/em&gt; this is an article about Tic-Tac-Toe, and why this solution even exists.&lt;/p&gt;

&lt;p&gt;I tend to think that &lt;strong&gt;Human being like patterns.&lt;/strong&gt; We're designed to find patterns and solve problems. Sometimes, our brains pattern matching inclinations can get us in trouble; conspiracies are essentially just us finding patterns even when &lt;a href="https://psychcentral.com/lib/patterns-the-need-for-order#3" rel="noopener noreferrer"&gt;they aren't there&lt;/a&gt;. Some patterns we've been picking apart and working on for thousands of years.&lt;/p&gt;

&lt;p&gt;One such pattern discovered at least as early as &lt;a href="https://en.wikipedia.org/wiki/Magic_square#History" rel="noopener noreferrer"&gt;190 BCE&lt;/a&gt; by Chinese mathematicians is the concept of a &lt;em&gt;Magic Square&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fd%2Fdb%2FMagic_Square_24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fd%2Fdb%2FMagic_Square_24.png" alt="picture of magic square"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tada? Yes it's just a box.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"But Kirk," you ask, "what's so special about this square?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well you see, all magic squares (including this one) have &lt;strong&gt;three (3)&lt;/strong&gt; very interesting properties.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the digits in the &lt;strong&gt;rows&lt;/strong&gt; of the square add to a particular number.&lt;/li&gt;
&lt;li&gt;All the digits in the &lt;strong&gt;columns&lt;/strong&gt; of the square must add to that same number.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;And&lt;/em&gt; all the digits in the &lt;strong&gt;diagonals&lt;/strong&gt; add to that number too!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do these rules feel familiar?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magic Squares care about the same patterns in grids made from squares that Tic-Tac-Toe does!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And the best part is, they have nothing to do with each other! When Tic-Tac-Toe started showing up in &lt;a href="https://en.wikipedia.org/wiki/Tic-tac-toe#History" rel="noopener noreferrer"&gt;Ancient Egypt&lt;/a&gt;, it didn't have anything to do with Magic Squares. Humans have just been enjoying patterns of squares in squares forever.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/kFIfiwvzJjbUsNbIg5/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/kFIfiwvzJjbUsNbIg5/giphy.gif" alt="best friends gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magic Squares&lt;/strong&gt; fall into the realm of &lt;a href="https://en.wikipedia.org/wiki/Recreational_mathematics" rel="noopener noreferrer"&gt;Recreational Mathematics&lt;/a&gt;, which is maths done at least partially for the purposes of entertainment, as opposed to research of practical application. It's also the maths most frequently done by amateur (unpaid mathematicians). Throughout history though, Mathematicians, Philosophers, and even Religious figures have studied and teased apart the nature of magic squares. Beyond 3x3 grids, they've looked at 4x4 and larger magic squares. They've looked at semi-magic squares and pseudo magic squares, and even some things given the brilliant name of &lt;em&gt;Most-Perfect Magic Squares&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Throughout history the patterns of magic squares have been claimed to have use in astronomical calculations, and even occult powers. There's quite a large body of examples, computations, and algorithms based on them. We've taken them apart and put them together over and over in the pursuit of understanding what do these patterns of numbers mean? And that's been terribly fun for everyone involved, but for the most part, generally, they have absolutely &lt;strong&gt;no purpose at all&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;They're just numbers in squares, with no more meaning than what we give them. Just some silly nonsense that we like to look at. Answers with no questions.&lt;/p&gt;

&lt;p&gt;Except for today. Today they're helping us solve Tic-Tac-Toe.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Making winning magic combos
&lt;/h2&gt;

&lt;p&gt;So now we know there are &lt;em&gt;magic squares&lt;/em&gt;, which care about the same arbitrary patterns that Tic Tac Toe cares about. How does that help us get to a solution.&lt;/p&gt;

&lt;p&gt;Well, let's look at the magic square for a 3x3 grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F1%2F1a%2FMagic_Squares_-_3x3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F1%2F1a%2FMagic_Squares_-_3x3.svg" alt="magic square 3x3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While magic squares get more complex in 4x4 grids and higher, with 3x3 grids we can confidently say a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the rows, columns, and diagonals in a 3x3 magic square add to fifteen (15)&lt;/li&gt;
&lt;li&gt;As importantly, any other 3 number combo in a 3x3 magic square Does Not add up to 15.&lt;/li&gt;
&lt;li&gt;There's only &lt;em&gt;one (1)&lt;/em&gt; way to align the numbers in a 3x3 grid to get a magic square (You can rotate the numbers around the center or flip them on an axis but it's still the same arrangement).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means if we can &lt;em&gt;programatically&lt;/em&gt; get all the 3 digits combos that sum to 15, we can get all the relevant rows, columns, and diagonals in Tic-Tac-Toe.&lt;/p&gt;

&lt;p&gt;The implementation of this ends up being far shorter that the lead up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Combination&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js-combinations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uniqueTriples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Combination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [[1, 2, 3], [1, 2, 4], [1, 2, 5] ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winningCombos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uniqueTriples&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// [[1, 5, 9], [1, 6, 8], [2, 4, 9], [2, 5, 8]...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only a few lines of code but there's a lot going on here so let's break it down step by step.&lt;/p&gt;

&lt;p&gt;The first thing we do is import the &lt;code&gt;Combination&lt;/code&gt; class from the &lt;a href="https://www.npmjs.com/package/js-combinatorics" rel="noopener noreferrer"&gt;js-combinatorics&lt;/a&gt; package. This package has a ton of useful tools for calculating &lt;a href="https://www.calculatorsoup.com/calculators/discretemathematics/combinations.php" rel="noopener noreferrer"&gt;permutations and combinations&lt;/a&gt; of items. &lt;/p&gt;

&lt;p&gt;We're using to the Combination class to create all the valid, &lt;em&gt;unique&lt;/em&gt; combinations of 3 numbers from the set of numbers from 1 to 9.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Combination&lt;/code&gt; class from this library is a Javascript &lt;a href="https://javascript.info/iterable" rel="noopener noreferrer"&gt;Iterable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each value is the same shape as the ones we saw in one original winning combos; &lt;strong&gt;an array of three (3) numbers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We convert our combination class to an array so we can do the next step; filtering those unique pairs down to just the values that add to 15. Thanks to magic squares we &lt;em&gt;know&lt;/em&gt; those values will be the rows, columns, and diagonals of our solution.&lt;/p&gt;

&lt;p&gt;To the filter method, we pass a callback inline that uses &lt;code&gt;reduce()&lt;/code&gt; to sum all the values in our triple and see if they add to 15.&lt;/p&gt;

&lt;p&gt;And our &lt;code&gt;hasWinner()&lt;/code&gt; function is none the wiser.&lt;/p&gt;

&lt;p&gt;The final part is the &lt;strong&gt;arrangement of our cells in the UI&lt;/strong&gt;. The only way this method works is if on the UI side, our cells are displayed in the right order. There are a few ways to accomplish this but the simplest is just to order our keys in the magic square arrangement so whatever calls the API gets them out in the order they're meant to be displayed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const keys = [2, 7, 8, 9, 5, 1, 4, 3, 6]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all it takes. No more manually writing out winning combos. And we can scale this for 4x4, 5x5, 6x6 etc... &lt;/p&gt;

&lt;h2&gt;
  
  
  4. So What's the Takeaway
&lt;/h2&gt;

&lt;p&gt;Honestly, I started this project planning to talk about object-oriented vs functional API design. And I might still do that. I had written the first version of this solution, and it worked really well, and that was going to be it.&lt;/p&gt;

&lt;p&gt;But then, at &lt;strong&gt;2:00 a.m. in the morning&lt;/strong&gt; when I should've been asleep, I was instead thinking about how tic-tac-toes remind me of tiny sudoku tables. And I remembered doing a cool sudoku once that had a &lt;em&gt;Magic Square&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/b6iVj3IM54Abm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/b6iVj3IM54Abm/giphy.gif" alt="woken up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I have always felt like coding is a creative endeavour.&lt;/strong&gt; I remember being told once, that &lt;em&gt;"creativity is just novel juxtapositions"&lt;/em&gt;. I could've done this the regular way, but this way, with this weird fact about magic squares, it just seemed a little more fun.&lt;/p&gt;

&lt;p&gt;It just felt like something to explore. I am far from the first person to make a Tic-Tac-Toe game. And I'm definitely not the first person to think of Magic Squares. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But maybe I'm the first one to put them together like this.&lt;/strong&gt; With React. With Typescript. And that was &lt;em&gt;fun for me&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So I hope this post and this code can provide you some measure of joy and insight. And even if you don't care about the squares stuff, I don't think it's a half bad implementation of Tic-Tac-Toe. It's got all the function composition and expression based logic I also enjoy. And I hope it inspires you to do things you enjoy as well. Not everything we do needs to have a direct purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can just do things, and write code, because it makes you happy.&lt;/strong&gt; In between all the &lt;em&gt;React fundamentals, and AWS fundamentals, and Docker fundamentals&lt;/em&gt;, and practicality and hireability, we should sneak in some time just for us.&lt;/p&gt;

&lt;p&gt;And like me and the folks who first thought about Magic squares, maybe 2000 years from now, someone will find the things you did just for fun, and use them to have fun too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwsud823c428fshol44t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwsud823c428fshol44t.gif" alt="flower costume dancing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you have any questions about the code, the squares, or the strategy, or if there's anything else you'd like me to cover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for your time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*Special thank you to all my friends at &lt;a href="//virtualcoffee.io"&gt;Virtual Coffee&lt;/a&gt; for encouraging me to do this (and debugging my css!)&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;See &lt;a href="https://github.com/tkshill/Reac-tac-toe" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the Github repo for this code.&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://codesandbox.io/s/github/tkshill/Reac-tac-toe" rel="noopener noreferrer"&gt;here&lt;/a&gt; for the editable, runnnable codesandbox where I made this.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://en.wikipedia.org/wiki/Magic_square" rel="noopener noreferrer"&gt;wikipedia&lt;/a&gt; article about magic squares has a lot more cool info about their history and properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, here's the main code for the solution if you'd just like to see what's going on here.&lt;/p&gt;

&lt;p&gt;App.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./GameClass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialGame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;initialGame&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="c1"&gt;// this is where we update the state of our application&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Restart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Restart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;initialGame&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// our tiny little cell component&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// I really dislike curly braces&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; won the game!`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFull&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The game is a draw!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'s turn to play!`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Putting it all together&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;ReacTacToe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gamebox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cellNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;statusMessage&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Restart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GameClass.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Combination&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js-combinatorics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// get every unique combination of 3 numbers and only keep the ones that sum to 15&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winningCombos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Combination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;winningCombos&lt;/span&gt;
    &lt;span class="c1"&gt;// get the corresponding grid items&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;comboNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;comboNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="c1"&gt;// if you find at least one with all Xs or all Os, there's a winner!&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="nx"&gt;comboValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// using reduce to add all our keys to an object with initial values of null;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// get the grid values&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// use reduce to make an object that counts all the Xs and Os&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Xs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Os&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Os&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// if there are more Xs on the board, it's O's turn.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Xs&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Os&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;hasWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// if there's a winner and it's X's turn, that means O just won. Otherwise, X just won.&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;isFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// no null values in the grid? board must be full&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;getCell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;setCell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// no winner yet, a valid name and an empty cell? Set grid cell to whoever's turn this is.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;cellNames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Styles.scss&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-around&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#gamebox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s1"&gt;". . ."&lt;/span&gt;
    &lt;span class="s1"&gt;". . ."&lt;/span&gt;
    &lt;span class="s1"&gt;". . ."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>react</category>
      <category>typescript</category>
      <category>gamedev</category>
      <category>maths</category>
    </item>
    <item>
      <title>Reduce in 5 Minutes</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Mon, 11 Oct 2021 16:30:52 +0000</pubDate>
      <link>https://forem.com/kirkcodes/reduce-in-5-minutes-462i</link>
      <guid>https://forem.com/kirkcodes/reduce-in-5-minutes-462i</guid>
      <description>&lt;p&gt;Here's a quick intro to the &lt;code&gt;reduce()&lt;/code&gt; method in Javascript/Typescript arrays, which is frequently perplexing when encountered in working code.&lt;/p&gt;

&lt;p&gt;The code here is written in Typescript but I've tried to keep it friendly for JS readers, and I'll post a link to the equivalent JS at the end. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's the point of reduce?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Reduce&lt;/code&gt; allows us to take a container of data (like an array) and fold it into another data structure.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reduce()&lt;/code&gt; method involves three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;container of values&lt;/strong&gt;, like an array, with which we need to update another structure (in sequence)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;function&lt;/strong&gt; that lets us update a value (typically called the &lt;em&gt;accumulator&lt;/em&gt;) based on an element from our array
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;updater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;SomeType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextValueFromArray&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SomeType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// whatever operations we want&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;updatedAccumulator&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequently this updater is written inline, directly inside the reduce function.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The last thing the reducer needs is an &lt;strong&gt;initial value&lt;/strong&gt; for our accumulator, for the first iteration of the function.
&lt;code&gt;Reduce&lt;/code&gt; is smart enough to realize that if we don't provide an initial value, it should use the first element of the array as the initial value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Omitting the initial value only works if &lt;em&gt;the accumulator is the same type as elements&lt;/em&gt;. An example to show this will be provided below.&lt;/p&gt;

&lt;p&gt;So, to recap, any reduce operation can be thought of as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;someArrayOfValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updater&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValueOfTheAccumulator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Let's look at some examples!&lt;/p&gt;

&lt;p&gt;First, let's see how we could do string concatenation using reduce. This involves 'folding' an array of strings into a single string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// our array of characters to fold&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;boSpelling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="c1"&gt;// our initial value for us to reduce into is an empty string &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you see, we write a function that understands how to add a letter to a value and return a new value. &lt;code&gt;Reduce&lt;/code&gt; takes that function, and our new value, and will pass each letter of our array to that function, bringing the result forward to serve as the accumulated value for the next iteration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bosName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;boSpelling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;nameSoFar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nameSoFar&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;updatedName&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;initialName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could also inline the initial value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bosName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;boSpelling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;nameSoFar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nameSoFar&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;updatedName&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bosName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "Bo Burnham" &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just to provide context, here is the &lt;code&gt;for&lt;/code&gt; loop version. This does the same as the code above, but here we update a mutable variable and use a &lt;code&gt;for&lt;/code&gt; block instead of a function expression.&lt;/p&gt;

&lt;p&gt;Some people find this preferable but it does require object mutation, unlike &lt;code&gt;reduce&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;concatenate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bosName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;concatenate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boSpelling&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bosName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;\\&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bo Burnham&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's make a custom &lt;strong&gt;sum&lt;/strong&gt; function using &lt;code&gt;reduce&lt;/code&gt;. Combining with es6 syntax allows for some very concise expressions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nextNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that since the accumulator &lt;code&gt;count&lt;/code&gt;, and the array elements are both numbers, we can omit the initial value and just let &lt;code&gt;reduce&lt;/code&gt; use the first value as the initial.&lt;/p&gt;

&lt;p&gt;In situations where they're not the same data type, doing this would cause an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nextNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// "54"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Examples
&lt;/h2&gt;

&lt;p&gt;We've hit the end of the main things I wanted to demonstrate with reduce (I told you this would be quick). But we can have a bit more fun and show how powerful and flexible it really is. These next examples are beyond the standard use cases of reduce and if you're still new to the concept, feel free to skip them. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reduce()&lt;/code&gt; method can fold a sequence of values into &lt;strong&gt;any&lt;/strong&gt; data structure you'd like, including another sequences.&lt;/p&gt;

&lt;p&gt;This makes it more powerful than its sibling methods, &lt;code&gt;map()&lt;/code&gt; and &lt;code&gt;filter()&lt;/code&gt;, which can only transform an array into another array. But that doesn't mean it can't do what they do as well.&lt;/p&gt;

&lt;p&gt;Here we make &lt;code&gt;map()&lt;/code&gt; from reduce. For each item in the original array, we apply the function to it and add to an accumulator, a new array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we can use it similarly to the &lt;code&gt;map()&lt;/code&gt; method we know&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyByThree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;multiplyByThree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;\\&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3,6,9,12,15,18,21,24,27,30&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;filter&lt;/code&gt; function is similar. Here, the function we pass in is a &lt;strong&gt;condition&lt;/strong&gt;, which is a function that accepts a variable of the same type as the ones in the array and returns a boolean).&lt;/p&gt;

&lt;p&gt;If the array item satisfies the condition (returns true), we add it to the new array, otherwise we pass along the new array as is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newLst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;newLst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newLst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

&lt;span class="c1"&gt;// our condition&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filterResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isEven&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;\\&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2,4,6,8,10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A &lt;em&gt;brief&lt;/em&gt; aside on types
&lt;/h3&gt;

&lt;p&gt;Another way we can compare the three methods in in terms of the &lt;code&gt;types&lt;/code&gt; they accept, and return. In pseudocode, the types of the three functions can be described as&lt;/p&gt;

&lt;p&gt;&lt;code&gt;map : (a -&amp;gt; b), Array a -&amp;gt; Array b&lt;/code&gt;&lt;br&gt;
Given a function that takes an &lt;code&gt;a&lt;/code&gt; and returns a &lt;code&gt;b&lt;/code&gt;, and an array of &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; will return an array of &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;filter : (a -&amp;gt; Bool) -&amp;gt; Array a -&amp;gt; Array a&lt;/code&gt;&lt;br&gt;
Given a function that takes an &lt;code&gt;a&lt;/code&gt; and returns a &lt;code&gt;boolean&lt;/code&gt;, and an array of &lt;code&gt;a&lt;/code&gt;, filter returns an array of &lt;code&gt;a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reduce : (b -&amp;gt; a -&amp;gt; b) -&amp;gt; b -&amp;gt; Array a -&amp;gt; b&lt;/code&gt;&lt;br&gt;
Given a function that takes a &lt;code&gt;b&lt;/code&gt; and an &lt;code&gt;a&lt;/code&gt; and returns a &lt;code&gt;b&lt;/code&gt;, an initial accumulator value &lt;code&gt;b&lt;/code&gt;, and an array of &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt; returns a &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I hope this provided some clarity and demystified one of the more powerful tools in the JS toolbelt.&lt;/p&gt;

&lt;p&gt;Let me know if this helped, or what other methods you want five minutes on!&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;See &lt;a href="https://www.typescriptlang.org/play?#code/PTAEEFQZwWwQwDYNAFzlFBTUB7AZqAE6YAmArgMaYBQ1IoA6gBZwqgCWUqT2ADjuwB2bfEVKUadMACVxVUIgQ4A7lzJcUOVHADW2KDhjYKOYXCGZCuAiVZxQACgTs9CwQsKE4ATwCUbklApUAAxHARAlB4YDmEtAyNcKMtQWzRoFEJKFDJiWnpQWXJ5IQA3cNLMDSZiPjhCFChguH8E41M0CytRUsQyKoAaUGdXOHd6r28h5XYo0GUmdgomeexBTFJULTJeNP1DbBxkqwwsihziRyFoTABHfsEqXylggCN-SDwyR5R2U25WMNMI1QOpQbtWPtEr0EP1HBRFJtkgoKBQyDAyAhWDhCP5XuhNv8xqBMAhMEZhKA8IRDLhcsNOGwXvQvj8-u4dntCA44Kj0ZjsYQAFwAZQOABVvLxMEN1gAPFAANT6mBCNJgABlGb4haAxUZJdLQABvYKgc2gAB01rNFuIFw5EKwJHAfIxWM0hGCAF9gsFqXcHigEN5uJxwVyOFxlIRZlh3EJnOtYtxsMRithWed2al2MRziHmWAKP5kViMGHBABzVNiDNWdakLjh4lCWbsRCgGFwvA4ulWXlo92Coa9qzIvB5iuzSysHOiZL+77Z0yW4IACRUmEqhCG6YkUeg8AaJMEODIVZWmjEiE42CigPYBGU2BIHVAvBppXYJGwrcE7adt2MocGwUBMOeESglA948FSU5sKS5KYJSwQLnBEw+Ao1TYG2vxASqa70AAcgA8uKACiAJsFE4amCG8w4jozYEMig78h6fbhsiUBwIkKBSn+XBIRSjSWhA7iYHKfG8GSWzQBByhhtG7BIKArzYMEn44N+v6BBpSjKGu+RgGKQzXvmcC8EMYyhvu8g4NKXi-P8CLuBp3DnpebDoEEwRtOAng+KReDKrCVSWvZmAOJykK7rEgEIGF-QheKPCukOAqes8JlAiCSg4DoChgQcJLSTAslVLlk6EBgQxkiCMHYIpqygCYmKBG+GSxtWbWmAi8Zzv86hCDWUVEWAaXhmUFRVKAADkvYRKN81uB4kzWN1o3NnECjQKNcmnKNxn0OeA5BaGojLPUvJYLV8lLSQ1AmIIFavDgIrSkgo2gAAvKAADa80AELzUM804GDC0LeDoPg2QUPzYQiOCIjTCI3AiMwPNAC6uVnQl+HIMBVJ9mCFlyLhu0tpJFUCVtvXPaY04AUTxF8dg-3zfNuXrpY2DeOeNwgS+8yxlge1Zi57gPmw3y-rVaCCCQXAtdecAkIE9gNXd8n2CTYyBPauTjKA6xKcBE11geaB6NUgJS+yNnK-2ZuYBbKrO4EMxqbw6DCbyKw6ykogE5hobXrLVLLtLQxvD1VY-cixBQJibBjso9SRPEliVNhtaCBz0BaHg9Sk+OcHymwM7OeyxkvW9OBQOziT-e9n2kkmVaRZTDgOIXRhiiE9T1cCd3+L9AB8JrUBafWvXLTqkC3nNmxzQ9lwA1Hld2z3awImxGkIkCv1DekMeEdggK85fQovtVBiAGLESawVTiVdiqtAN2w73NxzAAmP66kPpfS7j3DMfcB6YA3vFYOuI-rT1NHPH+R9nQr2AdA2BoBt7wL3uaY2hBHR7BPhzM+4N5o5QbuETAlolBVgcAAAyOr1F6A0UJDQ5FAH6UVdQAB1BAACIhgABJjR-xXgA70jDb5gAAFLqBolobSul2jCCkigIYPBLjcTgmOYYOBHJdksNw1coAppcDfHNHiRdfLIhML+BQ7086vDICgYI2jsCi1ihLewGI0CvDkr0WMcBAl-hduoP85d1JKAoEVIQGBMAa02vYR2-wpKfiqKYwQVt9R8EwI5OSk4Xa0S4JkvAs4wnqTcaBVIOA5rEHuHmQ4rwABWmBzigH8ZwoY3wRhpkpt-ZmbA2GQkLhLf6TgMBChYVWAGOMJ5IPwXlNerdQCCMEcs-RThgQ7xDgQBAGB-DILnhaaBOD-p4Lnr6OehD3DQLPkMheID-5GAAMzANGYNLADh25gNGlQ5mNC6E4AYcwzIP0vkcOltBH6+iCq8CFAIsREiOZvOkbIs2Kg8pcHgKMNqijaSpxiGkrhPDBn0BGr1KKH5YTCSgAANmgN4MwcoFBIBUFwfRbRjGEFDGwu8ZVMlQGyU0JmzzBDog0vdf6ANQAAKGG8oYAAWIYABWIYDKhgAHYhgAA4hgAE4hgAEYAAMeNxUVmJcAqZmg8DESlSYoUkqYDSvmYsoIc9Dn2sdW6kxECJB9zRJ4FCKAADC55hCyg0X6z1IbiDCEjd8Ng28q5+qGGazFZ4aIsDAkIeQbE3RZT7A4BNYbk3CF8F7Ws4cSRklElweo2B3pzFddKqAAxgj32JIYWYtZL4EXCgEUArTFErJpZE2sNUKwGxwoTK+VsACS7huE5E4dGTxqZvBIzWEcWsvFEhpHsAJaUQw3xJ0WNGSCgQERTuJJYGkhB67DOgOiIBkyfX4D9R2l1TrCAesQV6i0X6HX-qgIGqgwbciJojVGzRbsFRxqA+WpN8GcGIZQHGp5BgyQgrBTa0lsLqWUyRYIMRxKAH93A74DFuVwAABFFTgGIuGiiDHdQ9skpUdweK35dKsiOycCBdakq5eqa2VBxLBAcCEDYyAAz3i0OwKsZ5LilI4AQQWZA6mUhYHnewuGfygCrF4KAvBNpsWcbQ0AABNIWPtkDBHWDuUA+mlN1OLkYWivV+nKVAEu6QGpxLwAs4beCImUiIGIBrUMUltR+XoFu0WfGBMWepLSca0SknLFAuSFMbELrTD-LwWSEc9ExxzNeft4Xmiaz1uMYtnF4r2HNutLC1AiOhYADxwCGK8SeDgvgUGEOycUOBwClZDLqPufsvAwCFC0ID7whgBQuotj1upXjzJnrcg+RCvOYECpMSD0Uy0wbDcRd2x2fBCm2zjC+WAYArpu94RbnqTmnLEA6QG1pLSoaw9dor0cRvS3G5NsrDgZzPcEK93weNrlDA9Y84IaVMyqVE5V-44ZuEwFUvUcS+icsrGhwVjCwOny1N4r8KAk5rFwReiQdspgu13z-PV-tkdK7u3a1MJI2iZgwVan7EV7LTA1mRG1utvlOBriI8Ju6vXBuM+Z4Icb4aeBxKFA4ObfF3vLcMWSMYq2DivY2ws3UcAdufe+4fNbJ2ooOGWXPc7obhAhAx-zF062rcPbyzDs3S2p7Aa+y7lXYOcAa46ToKHT2XsXX8M70PAB+X71oAce8i+mV7j3yTx8mDjEPofzS6gz577PCfllI4WY8+gZ4lINQ0FUXN5IcNsHdL8MrwNvDimUFoSZco-3+oQcHtlAAqUAby29RlIvVgfQ-pWerZQAUnlX9X6-0zWgFT5kOEupS6HMkKg0LshU4ia4P9ULDgO-sC7z3vvsoaPT4V5YU-acL8RbulDqAs+SCP+H1AICq9MCvQkwqFsRmNKRsisaCflUO-nRtQnhqAYwi-lYFSpARmGRmIqgW-ufnRhuI5JgF8EgOVuGDwAgLwFwNpmgcrCYkrEztWMZOaEAA"&gt;here&lt;/a&gt; for the full code in a sandboxed environment, in both TS and JS versions.&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce"&gt;here&lt;/a&gt; for some more official docs on the method, it's overloads, etc.&lt;/li&gt;
&lt;li&gt;Note there's a small error in the live example where the &lt;code&gt;isOdd&lt;/code&gt; function actually checks for evenness, and I am being too lazy to fix it and get a new URL.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>functional</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Solving the Dominoes problem with Graph Theory and Typescript</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Wed, 07 Apr 2021 13:20:07 +0000</pubDate>
      <link>https://forem.com/kirkcodes/solving-the-dominoes-problem-with-graph-theory-and-typescript-45f2</link>
      <guid>https://forem.com/kirkcodes/solving-the-dominoes-problem-with-graph-theory-and-typescript-45f2</guid>
      <description>&lt;h2&gt;
  
  
  Prelude
&lt;/h2&gt;

&lt;p&gt;This is a very short article which talks about using graph theory to solve my latest code challenge.&lt;/p&gt;

&lt;p&gt;Every two weeks my online community group, &lt;a href="https://virtualcoffee.io/" rel="noopener noreferrer"&gt;Virtual Coffee&lt;/a&gt; picks a new challenge for us all to work on together.&lt;/p&gt;

&lt;p&gt;This fortnight we've been working on the &lt;a href="https://exercism.io/tracks/javascript/exercises/dominoes" rel="noopener noreferrer"&gt;Dominoes problem&lt;/a&gt; on &lt;a href="https://www.exercism.io" rel="noopener noreferrer"&gt;https://www.exercism.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I tried to solve this &lt;a href="https://dev.to/kirkcodes/solving-the-dominoes-exercism-problems-with-active-patterns-in-f-384d"&gt;previously&lt;/a&gt; using F# without having to do any  recursion or traversals. That &lt;em&gt;basically&lt;/em&gt; worked, but failed at a few edge cases and ultimately wasn't a complete solution.&lt;/p&gt;

&lt;p&gt;While looking at other implementations I stumbled upon &lt;a href="https://exercism.io/tracks/fsharp/exercises/dominoes/solutions/8d97e2a04a40484eae7cb0d6c30f515b" rel="noopener noreferrer"&gt;this solution&lt;/a&gt; which proposed that you could solve the problem by modelling the dominoes as a &lt;a href="https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)" rel="noopener noreferrer"&gt;Graph&lt;/a&gt;. I liked the approach conceptually, but didn't want to just recreate the answer in F# again so I figured I'd try it with Typescript.&lt;/p&gt;

&lt;p&gt;If you just want see the code, feel free to skip to here.&lt;/p&gt;

&lt;p&gt;So without further ado, let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Paraphrasing &lt;a href="https://www.exercism.io" rel="noopener noreferrer"&gt;exercism&lt;/a&gt;, "Write a function &lt;code&gt;canChain&lt;/code&gt; to determine whether a set of dominoes (an array of tuples) can be chained."&lt;/p&gt;

&lt;p&gt;e.g. The dominoes &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1, 2), (1, 3), (2, 3)&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;can be chained together as &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1, 2) (2, 3) (3, 1)&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;where each domino is joined at matching number terminals.&lt;/p&gt;

&lt;p&gt;Conversely the dominoes &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1, 2), (1, 3), (4, 4)&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;cannot be chained because there is no domino&lt;br&gt;
that can connect to &lt;strong&gt;(4, 4)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some extra rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty arrays should return true &lt;/li&gt;
&lt;li&gt;The ends of the domino set should also match (making a perfect loop)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nf"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Methodology
&lt;/h3&gt;

&lt;p&gt;We can model our set of dominoes as a graph where each domino represents two nodes (one for each number on the domino) and the edge/line/arrow that connects them.&lt;/p&gt;

&lt;p&gt;When two dominoes have the same number, that means at least one of their nodes overlap and they can be chained.&lt;/p&gt;

&lt;p&gt;For example, take the set of Dominoes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1, 4) (2, 4) (3, 4) (4, 5) (5, 6)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We could model them as the following graph:&lt;/p&gt;

&lt;p&gt;&lt;a title="AxelBoldt at English Wikipedia, Public domain, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Tree_graph.png" rel="noopener noreferrer"&gt;&lt;img alt="Tree graph" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fd%2Fda%2FTree_graph.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By observation, we can see that while some of these can be chained, there's no way to get from say, node 1 (from our (1, 4) domino, though all the other nodes, and back to node 1). We don't have another '1' to pair it with.&lt;/p&gt;

&lt;p&gt;Thus we can rephrase the problem of &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Can the dominoes chain?"&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;to the graph centric questions of &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Do these nodes all connect?"&lt;/em&gt; and &lt;em&gt;"Can we get from any node to every other node and back to the start?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It turns out, in graph theory, this type of configuration requirement has a name: A Euler Graph. &lt;/p&gt;

&lt;p&gt;&lt;a title="S Sepp, Public domain, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Labelled_Eulergraph.svg" rel="noopener noreferrer"&gt;&lt;img alt="Labelled Eulergraph" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F7%2F72%2FLabelled_Eulergraph.svg%2F256px-Labelled_Eulergraph.svg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Euler graph is definied as a graph having a &lt;a href="https://en.wikipedia.org/wiki/Eulerian_path" rel="noopener noreferrer"&gt;Eulerian cycle&lt;/a&gt;, which is exactly what we just described:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a Eulerian cycle is a path starting and ending on the same vertex) that visits each edge exactly once. - Wikipedia&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that all we need to do to prove if our dominoes can chain is to prove that the graph those dominoes&lt;br&gt;
represent has a Euler cycle.&lt;/p&gt;

&lt;p&gt;And THAT proof it turns out, also has a formal definition, known as &lt;strong&gt;Euler's Theorem&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A Connected graph has an Euler cycle if and only if every vertex has even degree".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So our solution now has two parts:&lt;/p&gt;

&lt;p&gt;First, we check if the dominoes can be converted to a &lt;strong&gt;Connected&lt;/strong&gt; graph, which we've already looked at.&lt;/p&gt;

&lt;p&gt;Second, we check if every vertex (number) in our set of dominoes has an &lt;strong&gt;even degree&lt;/strong&gt; (appears as a multiple of two).&lt;/p&gt;

&lt;p&gt;&lt;a title="Akshaya Mathew, CC BY-SA 4.0 &amp;lt;https://creativecommons.org/licenses/by-sa/4.0&amp;gt;, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:A_graph_with_central_vertex_having_degree_as_number_of_vertices_minus_one_and_the_remaining_vertices_with_degree_one.PNG" rel="noopener noreferrer"&gt;&lt;img alt="A graph with central vertex having degree as number of vertices minus one and the remaining vertices with degree one" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F2%2F2e%2FA_graph_with_central_vertex_having_degree_as_number_of_vertices_minus_one_and_the_remaining_vertices_with_degree_one.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Th graph above is an example of a graph that is connected (you can get from one node to any other node) but it's nodes don't have an even number of edges. Even without the numbers we know this graph cannot form a loop.&lt;/p&gt;

&lt;p&gt;&lt;a title="Not me, CC BY-SA 4.0 &amp;lt;https://creativecommons.org/licenses/by-sa/4.0&amp;gt;, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Cycle_graph.png" rel="noopener noreferrer"&gt;&lt;img alt="Cycle graph" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Ff%2Ffa%2FCycle_graph.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This graph on the other hand has each node with an even number of edges joining it to other nodes, and thus can loop.&lt;/p&gt;

&lt;p&gt;Now that we've explored some of the theory behind our proposed solution, let's see if we can enforce these concepts with Typescript.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Establishing our domain
&lt;/h3&gt;

&lt;p&gt;Since it's Typescript, we'll start the way we always do by defining the types that establish the domain we're working with. We want to define what a Domino is (in this implementation) as well as some of the data structures related to Graph modelling. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// A representation of the set of edges in a graph&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt;&lt;span class="p"&gt;[][];&lt;/span&gt; &lt;span class="c1"&gt;// Representation of a graph as a matrix of filled/unfilled cells&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][];&lt;/span&gt; &lt;span class="c1"&gt;// Representation as a list of connected nodes&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Functions that test our Euler's theory&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The three types above, &lt;code&gt;EdgeSet&lt;/code&gt;, &lt;code&gt;AdjacencyMatrix&lt;/code&gt;, and &lt;code&gt;AdjacencyList&lt;/code&gt; represent three common ways of representing graphs. Our list of dominoes is passed into our code as an &lt;code&gt;EdgeSet&lt;/code&gt;; a sequence representing pairs of connected nodes.&lt;/p&gt;

&lt;p&gt;However to determine if we have a Eulerian cycle, we'll have to convert our &lt;code&gt;EdgeSet&lt;/code&gt; to an &lt;code&gt;AdjacencyMatrix&lt;/code&gt; and then convert that to an &lt;code&gt;AdjacencyList&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So let's define some functions to do just that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating our conversion functions
&lt;/h3&gt;

&lt;p&gt;First we need to define two small helper functions&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// yes, this returns itself.&lt;/span&gt;

&lt;span class="c1"&gt;// simplifies an edgeset down to its unique nodes by converting to and from a set&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can define a function that converts an &lt;code&gt;EdgeSet&lt;/code&gt; into the appropriate &lt;code&gt;AdjacencyMatrix&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title="Dcoetzee, Public domain, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Graph_isomorphism.svg" rel="noopener noreferrer"&gt;&lt;img alt="Graph isomorphism" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F3%2F3c%2FGraph_isomorphism.svg%2F256px-Graph_isomorphism.svg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodeToIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// initial graph of all false values&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;initMatrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addToMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addToMatrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initMatrix&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and a function that turns an &lt;code&gt;AdjacencyMatrix&lt;/code&gt; into an &lt;code&gt;AdjacencyList&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toAdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;row&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// add indexes&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// filter unfilled cells&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// keep indexes&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We won't dive too deep into the code behind these functions except to say that what matters most to us is the &lt;code&gt;AdjacencyList&lt;/code&gt;. An &lt;a href="https://en.wikipedia.org/wiki/Adjacency_list" rel="noopener noreferrer"&gt;Adjacent List&lt;/a&gt; is a way of representing finite graphs where each node in the list contains the set of nodes adjacent to that node.&lt;/p&gt;

&lt;p&gt;&lt;a title="Thedsadude, CC BY 3.0 &amp;lt;https://creativecommons.org/licenses/by/3.0&amp;gt;, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Dsa_adj_list.png" rel="noopener noreferrer"&gt;&lt;img alt="Dsa adj list" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Ff%2Ff6%2FDsa_adj_list.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;e.g. Earlier, we had the dominoes &lt;br&gt;
&lt;strong&gt;(1, 2), (1, 3), (4, 4)&lt;/strong&gt;&lt;br&gt;
We said that we could represent these in typescript as the Edge set&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[[1, 2], [1, 3], [4, 4]]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But we could also put them in the shape of the Adjacency list &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[[2, 3], [1], [1], []]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this representation, each item in the outer list represents a node, and each inner list is the the &lt;em&gt;adjacent&lt;/em&gt; nodes to that one.&lt;/p&gt;

&lt;p&gt;So we can read this adjacency list as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node 1 has nodes 2 and 3 adjacent to it&lt;/li&gt;
&lt;li&gt;Node 2 has node 1 adjacent to it&lt;/li&gt;
&lt;li&gt;Node 3 has node 1 adjacent to it&lt;/li&gt;
&lt;li&gt;Node 4 has no nodes adjacent to it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this corresponds perfectly to what we see looking at the original dominoes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing our search function
&lt;/h3&gt;

&lt;p&gt;&lt;a title="Mre, CC BY-SA 3.0 &amp;lt;https://creativecommons.org/licenses/by-sa/3.0&amp;gt;, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Depth-First-Search.gif" rel="noopener noreferrer"&gt;&lt;img alt="Depth-First-Search" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F7%2F7f%2FDepth-First-Search.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a data structure showing our nodes and who they're adjacent to, we need a function that actually checks to see whether we can get to every node from any one starting node.&lt;/p&gt;

&lt;p&gt;There are a few options for what we can use to do this but here we'll be applying the &lt;a href="https://en.wikipedia.org/wiki/Depth-first_search#:~:text=Depth%2Dfirst%20search%20(DFS),along%20each%20branch%20before%20backtracking." rel="noopener noreferrer"&gt;Depth-First Search&lt;/a&gt;, a well known algorithm for traversing tree/graph data structures.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Depth-first&lt;/em&gt; means it will travel all the way to the end of a 'tree' from the root before backtracking (unlike its counterpart, &lt;em&gt;Breadth-first search&lt;/em&gt;, which will check all paths on one level before going lower).&lt;/p&gt;

&lt;p&gt;So our depth-first search (dfs) function will (recursively) go from node to adjacent nodes as defined in our Adjacency list. To help it, we'll make an array representing all the nodes available called &lt;code&gt;statuses&lt;/code&gt;. Every time the dfs meets a node it hasn't encountered before it will update the array of node statuses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the dfs visits all available nodes as it traverses through the adjacency list, then voila, that means the graph &lt;em&gt;must&lt;/em&gt; be connected.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DFS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AdjacencyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DFS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;adjacent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adjacent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// get unvisited nodes&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;unvisitedNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unvisitedNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note that this implementation of dfs doesnt return a value, it simply updates the array of node statuses. Then it checks to see if the current node has any adjacent nodes that haven't been visited, and recursively calls itself with those.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining our Euler Conditions
&lt;/h3&gt;

&lt;p&gt;Now that we've defined our data structures and our search function, it's finally time to put it together and create the function that will actually check to see if our Eulerian cycle exist. Each one is designed to accept the original list of dominoes and return whether our conditions were satisfied or not.&lt;/p&gt;

&lt;p&gt;First our &lt;code&gt;isConnected&lt;/code&gt; function which uses the code we defined above to determine if the domino array representing the &lt;code&gt;EdgeSet&lt;/code&gt; of a graph is a connected graph by checking if every node in the visited array .&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isConnected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toAdjacencyList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// time to spelunk&lt;/span&gt;
  &lt;span class="nf"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next we make a function &lt;code&gt;allEvenDegree&lt;/code&gt; to see if our edges all have an even number of representations. We do this by folding the array of dominoes into a Map (object) of keys representing our nodes, and values representing the amount of times they appear in the array.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allEvenDegree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// creates a map of nodes and the amount of times they appear&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addToMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;nodeCounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// concat + flatten&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addToMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// fold into a map&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// back to array&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nodeCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isEven&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;Finally, after all that, all that remains is to define our &lt;code&gt;canChain&lt;/code&gt; function that assembles all our logic into one conveniently exposed function. &lt;code&gt;canChain&lt;/code&gt; checks to see if a set or dominoes has all even degree &lt;strong&gt;and&lt;/strong&gt; (&amp;amp;&amp;amp;) is a connected graph.*&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;allEvenDegree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isConnected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;*If you remember, we said at the beginning that empty arrays should all evaluate to true, so we used an or (||) operation to stick that clause onto the rest of our &lt;code&gt;canChain&lt;/code&gt; operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Resources
&lt;/h2&gt;

&lt;p&gt;If you've made it this far, thank you for reading about my little exploration of graphs with Typescript. I just want to leave you with a few extra resources if this topic piqued your interests.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tkshill/typescript_dominoes_exercism/blob/main/src/index.ts" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is a link to full solution (with full notes)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=LFKZLXVO-Dg&amp;amp;t=704s" rel="noopener noreferrer"&gt;This video&lt;/a&gt; does a good job in my opinion of explaining all the basic Graph Theory terminology we touched on here.&lt;/li&gt;
&lt;li&gt;And &lt;a href="https://www.youtube.com/watch?v=52NDeYkVek0&amp;amp;t=608s" rel="noopener noreferrer"&gt;this video&lt;/a&gt; walks through using how to use an Adjacency list and depth-first search to find out if a graph is connected or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please leave a comment if you have an questions, queries, concerns, qualms, or critiques.&lt;/p&gt;

&lt;p&gt;Thank you for your time. :)&lt;/p&gt;

&lt;p&gt;Here's the code in its entirety&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Solution &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// A representation of the set of edges in a graph&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt;&lt;span class="p"&gt;[][];&lt;/span&gt; &lt;span class="c1"&gt;// Representation of a graph as a matrix of filled/unfilled cells&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][];&lt;/span&gt; &lt;span class="c1"&gt;// Representation as a list of connected nodes&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Functions that test our Euler's theory&lt;/span&gt;

&lt;span class="c1"&gt;// -------------------------- HELPER FUNCTIONS --------------------------&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// yes, this returns itself.&lt;/span&gt;

&lt;span class="c1"&gt;// simplifies an edgeset down to its unique nodes by converting to and from a set&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// ------------------------- CONVERSION FUNCTIONS -------------------&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EdgeSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodeToIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// initial graph of all false values&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;initMatrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addToMatrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Domino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nodeToIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addToMatrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initMatrix&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toAdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyMatrix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;AdjacencyList&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;row&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatrixValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// add indexes&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// filter unfilled cells&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// keep indexes&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* --------------------- IMPLEMENTATION ---------------------------------

Our depthfirstsearch (dfs) function checks to see what nodes can be visited from other nodes.
It updates the visited array every time it gets to a new node.
If a graph is connected, dfs should visit every node.

*/&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DFS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AdjacencyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DFS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;adjacent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adjacent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// get unvisited nodes&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;unvisitedNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unvisitedNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// determine if dominoes represent connected graph&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isConnected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeStatus&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toAdjacencyList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// time to spelunk&lt;/span&gt;
  &lt;span class="nf"&gt;depthFirstSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;statuses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// check if every number in the dominoes has an even number of representations&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allEvenDegree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// creates a map of nodes and the amount of times they appear&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addToMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;nodeCounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// concat + flatten&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addToMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// fold into a map&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// back to array&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nodeCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isEven&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// PUTTING IT ALL TOGETHER&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canChain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EulerCondition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;allEvenDegree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isConnected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dominoes&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>typescript</category>
      <category>exercism</category>
      <category>algorithms</category>
      <category>graphtheory</category>
    </item>
    <item>
      <title>Solving the Dominoes Exercism Problems with Active Patterns in F#</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Tue, 30 Mar 2021 22:32:09 +0000</pubDate>
      <link>https://forem.com/kirkcodes/solving-the-dominoes-exercism-problems-with-active-patterns-in-f-384d</link>
      <guid>https://forem.com/kirkcodes/solving-the-dominoes-exercism-problems-with-active-patterns-in-f-384d</guid>
      <description>&lt;p&gt;This is my solution implementation of the &lt;a href="https://exercism.io/tracks/fsharp/exercises/dominoes"&gt;Dominoes problem&lt;/a&gt; on exercism.io using F#.&lt;/p&gt;

&lt;p&gt;Edit: There is a slight problem with this solution (that I noticed right after I posted). An edge case that I failed to consider that requires a very quirky rewrite to fix. Leaving this solution up as I feel it still demonstrates a decent approach to solving the problem. Kudos to anyone who can spot the quirk though.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's the problem?
&lt;/h2&gt;

&lt;p&gt;The original question is essentially, &lt;strong&gt;"Given a list of dominoes, can you determine if they can be matched or &lt;em&gt;chained&lt;/em&gt; from end to end?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have to provide the interface &lt;code&gt;canChain&lt;/code&gt;. &lt;code&gt;canChain&lt;/code&gt; is a function that accepts a list of tuples representing a domino and returns true or false&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="n"&gt;dominoes&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="c1"&gt;// to be implemented &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  e.g. of chainable set
&lt;/h4&gt;

&lt;p&gt;The dominoes &lt;/p&gt;

&lt;p&gt;&lt;code&gt;(2, 4)(2, 5)(3, 4)(3, 5)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;can be "chained" to make &lt;/p&gt;

&lt;p&gt;&lt;code&gt;(3, 4)(4, 2)(2, 5)(5, 3)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  e.g. of non-chainable set
&lt;/h4&gt;

&lt;p&gt;The dominoes &lt;code&gt;(2, 4)(2, 5)(6, 6)(3, 5)&lt;/code&gt; cannot be "chained because &lt;code&gt;(6, 6)&lt;/code&gt; has no domino it can be paired with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional stipulations
&lt;/h3&gt;

&lt;p&gt;In additional, the problem imposes the following rules&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An empty list is considered a valid chain.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt; 
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A single domino is considered a valid chain only if it is a double (has the same number on both sides)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// false &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The ends of the list must also be able to be joined&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt; 
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You may have multiple copies of the same domino in the list.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Think about our solution
&lt;/h2&gt;

&lt;p&gt;I would love to have the mathematical training to explicitly define my solution, but I don't so I'll attempt to briefly explain my methodology.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base case: No doubles, no repeats
&lt;/h3&gt;

&lt;p&gt;Let examine the simplest case. A sequence of &lt;em&gt;normal&lt;/em&gt; dominoes (no doubles) &lt;em&gt;with no repeats&lt;/em&gt; will match if there's an even number of every number represented on a domino. For example&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[(3, 5); (2, 5); (2, 3)]&lt;/code&gt; resolves to two (3)s, two (2)s, and two (5)s. So we can say with certainty that this can be chained.&lt;/p&gt;

&lt;p&gt;Compare this to &lt;code&gt;[(3, 5); (2, 5); (2, 3); (4, 6); (3, 4)]&lt;/code&gt; has two (2)s, three (3)s, two (4)s, and one (6). This cannot pass because there will never be a match for the single (6), nor the third (3).&lt;/p&gt;

&lt;h3&gt;
  
  
  More complexity: Adding Doubles
&lt;/h3&gt;

&lt;p&gt;Doubles presents an interesting case because adding doubles breaks our reasoning above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[(3, 5); (2, 5); (2, 3); (6, 6)]&lt;/code&gt; has an even number of all digits but this clearly won't chain.&lt;/p&gt;

&lt;p&gt;Luckily, if we separate doubles from the original normal theory, they actually integrate nicely. You see, doubles would like the right clause in an of function. &lt;strong&gt;So long as the number in the double can be found in the normal dominoes, a double can be added in with no effect on the result.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);]&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now we can describe our algorithm as &lt;em&gt;if all the numbers in normal dominoes have an even count, and all numbers in doubles are found in at least one normal, the dominoes are chainable.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Even more complexity, adding repeats
&lt;/h3&gt;

&lt;p&gt;Repeats can cause our current implementation to fail in a similar way to doubles. If the numbers in the repeated dominoes are not represented in the normal dominoes, the sequence won't be chainable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer luckily, is the same as with the double. We have to consider the repeats separately, and check to ensure that at least one of the numbers in a repeat are in the normal dominoes. If they are, the repeat passes.&lt;/p&gt;

&lt;p&gt;In fact, it turns out that doubles are valid if they match with either normals or repeats.&lt;/p&gt;

&lt;p&gt;Let's update our algorithm again. &lt;em&gt;If all the numbers in normal dominoes have an even count, and all repeats have at least one number represented in normals, and all numbers in doubles are found in at least one normal or repeat, the dominoes are chainable.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Oops, one more edge case.
&lt;/h3&gt;

&lt;p&gt;We've done well so far, but it turns out there's one more case we haven't considered.&lt;/p&gt;

&lt;p&gt;What if there are no normals? What if we just have repeats and doubles? In that case, something slightly interesting happens. In the case of no normals, our repeats take the place of the normals as the dominant group. So long as each repeating pair have one matching number with another repeating pair, they are chainable. Double interaction remains the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our final algorithm now becomes (including the smaller one off requirements), a sequence of dominoes is chainable if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The sequence is empty.&lt;/li&gt;
&lt;li&gt;The sequence has one &lt;em&gt;Double&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The sequence has a set of pairs where each pair has a number shared by at least one other pair, and a set of doubles where the number in each double is shared by at least one pair.&lt;/li&gt;
&lt;li&gt;The sequence has a set of normal dominoes where every number in the set is represented in an even number of dominoes, a set of pairs where each pair has at least one number represented in the set of normals, and a set of doubles where each double's number is represented at least once in the set of pairs or normals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Finally from here we have everything we need to write the code to solve this problem. I've included a code snippet of the full solution below.&lt;/p&gt;

&lt;p&gt;Note the type &lt;code&gt;blob&lt;/code&gt; (I couldn't think of a better name at the time) that we've created to keep all the data we need to determine whether a list of tuples is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;doubles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
      &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
      &lt;span class="n"&gt;normals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our strategy will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sort the incoming tuple list&lt;/li&gt;
&lt;li&gt;Fold the list of tuples into a blob&lt;/li&gt;
&lt;li&gt;Match the blob with the right combination of cases to see if it represents a chainable domino stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what the final solution looks like. Unfortunately walking through exactly how this code works is beyind the scope of this article, but I'm hoping that with the little walkthrough above, the intent of the implementation is clear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// a type representing the data we need to see if a &lt;/span&gt;
&lt;span class="c1"&gt;// list of dominoes is chainable.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;doubles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
      &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
      &lt;span class="n"&gt;normals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// the initial state of our blob&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;emptyBlob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;doubles&lt;/span&gt;&lt;span class="o"&gt;=[];&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="o"&gt;=[];&lt;/span&gt; &lt;span class="n"&gt;normals&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This is our suite of comparison functions.&lt;/span&gt;
&lt;span class="c1"&gt;// Each returns true or false and we will mix &lt;/span&gt;
&lt;span class="c1"&gt;// and match them together in our checks for &lt;/span&gt;
&lt;span class="c1"&gt;// valid chainable dominoes.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EmptyBlob&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(=)&lt;/span&gt; &lt;span class="n"&gt;emptyBlob&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EmptyDoubles&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doubles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EmptyPairs&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EmptyNormals&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEmpty&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;OneDouble&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doubles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EvenNormals&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;DoublesMatchNormals&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containsKey&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doubles&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;PairsMatchNormals&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containsKey&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt; 
                                &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containsKey&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt; 

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;PairsCombine&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;canMatch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canMatch&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt; 
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;DoublesMatchPairs&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;canMatch&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; 
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canMatch&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doubles&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;JustDomino&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;OneDouble&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;EmptyPairs&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;EmptyNormals&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;// This is the actual function that checks to see &lt;/span&gt;
&lt;span class="c1"&gt;// if our blob is the right 'shape' that represents a&lt;/span&gt;
&lt;span class="c1"&gt;// chainable list of dominoes.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;isChain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;EmptyBlob&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;JustDomino&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;DoublesMatchPairs&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;PairsCombine&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;EmptyNormals&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;EvenNormals&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoublesMatchNormals&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;DoublesMatchPairs&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;PairsMatchNormals&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addKey&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ContainsKey&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; 
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nn"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normals&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;newNorms&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;normals&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newNorms&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// These functions update the three attributes of our blob. type correctly&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addNormal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;addKey&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addDouble&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="n"&gt;double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;doubles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distinct&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;double&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doubles&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addPair&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distinct&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// We make heave use of active patterns like this&lt;/span&gt;
&lt;span class="c1"&gt;// to make our match statements more readable&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(|&lt;/span&gt;&lt;span class="nc"&gt;EmptyList&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="o"&gt;|)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;EmptyList&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Normal&lt;/span&gt; &lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Our 'parser'.&lt;/span&gt;
&lt;span class="c1"&gt;// This converts our list of tuples to a single blob.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;dominos&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;dominos&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;EmptyList&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addDouble&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; 
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addPair&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Normal&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addNormal&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;

&lt;span class="c1"&gt;// Aligns all dominoes so their smallest value is on the left.&lt;/span&gt;
&lt;span class="c1"&gt;// This will help up when we need to check if two dominoes&lt;/span&gt;
&lt;span class="c1"&gt;// are the same.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;polarize&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;domino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;domino&lt;/span&gt;

&lt;span class="c1"&gt;// The actual function we expose that puts everything&lt;/span&gt;
&lt;span class="c1"&gt;// above together.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;canChain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;polarize&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;emptyBlob&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isChain&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>fsharp</category>
      <category>exercism</category>
      <category>codereview</category>
      <category>practice</category>
    </item>
    <item>
      <title>Solving the Protein Translator problem using F# and FParsec</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Mon, 22 Mar 2021 13:58:22 +0000</pubDate>
      <link>https://forem.com/kirkcodes/solving-the-protein-translator-problem-using-f-and-fparsec-362n</link>
      <guid>https://forem.com/kirkcodes/solving-the-protein-translator-problem-using-f-and-fparsec-362n</guid>
      <description>&lt;p&gt;This article/workbook is my attempt to solve the &lt;a href="https://exercism.io/tracks/fsharp/exercises/protein-translation"&gt;Protein Translation&lt;/a&gt; Problem on exercism.io. The whole thing was done in a &lt;a href="https://github.com/tkshill/protein-translation/blob/master/fparsec_exercism.ipynb"&gt;.Net Interactive Workbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last week, I tried this problem using Haskell (you can see the solution &lt;a href="https://github.com/tkshill/protein-translation/blob/master/src/ProteinTranslation.hs"&gt;here&lt;/a&gt;) as an exploration of point free style and composition.&lt;/p&gt;

&lt;p&gt;So let's now attempt this problem another way, using &lt;a href="https://www.quanttec.com/fparsec/"&gt;FParsec&lt;/a&gt;, a fully functional parser combinator library.&lt;/p&gt;

&lt;p&gt;Without getting too much into the details, Parser Combinator libraries operate on the principle of building parsers for large, complex, or intricate data structure, by combining smaller parsers together.&lt;/p&gt;

&lt;p&gt;So let's jump in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Describing the problem space
&lt;/h2&gt;

&lt;p&gt;(Taken from exercism):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RNA&lt;/strong&gt; can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;RNA: "AUGUUUUCU"&lt;/em&gt; =&amp;gt; translates to&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Codons: "AUG", "UUU", "UCU"&lt;/em&gt; =&amp;gt; which become a polypeptide with the following sequence =&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Protein: "Methionine", "Phenylalanine", "Serine"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are also three terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated.&lt;/p&gt;

&lt;p&gt;All subsequent codons after are ignored, like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;RNA: "AUGUUUUCUUAAAUG"&lt;/em&gt; =&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Codons: "AUG", "UUU", "UCU", "UAA", "AUG"&lt;/em&gt; =&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Protein: "Methionine", "Phenylalanine", "Serine"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note the stop codon "UAA" terminates the translation and the final methionine is not translated into the protein sequence.&lt;/p&gt;

&lt;p&gt;Below are the codons and resulting Amino Acids needed for the exercise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AUG -&amp;gt; Methionine&lt;/li&gt;
&lt;li&gt;UUU, UUC -&amp;gt; Phenylalanine&lt;/li&gt;
&lt;li&gt;UUA, UUG -&amp;gt; Leucine&lt;/li&gt;
&lt;li&gt;UCU, UCC, UCA, UCG -&amp;gt; Serine&lt;/li&gt;
&lt;li&gt;UAU, UAC -&amp;gt; Tyrosine&lt;/li&gt;
&lt;li&gt;UGU, UGC -&amp;gt; Cysteine&lt;/li&gt;
&lt;li&gt;UGG -&amp;gt; Tryptophan&lt;/li&gt;
&lt;li&gt;UAA, UAG, UGA -&amp;gt; STOP&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Defining our goal
&lt;/h2&gt;

&lt;p&gt;To call this solution solved, our requirements are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define a function proteins that accepts a &lt;code&gt;string&lt;/code&gt;, and returns an &lt;a href="https://fsharpforfunandprofit.com/posts/the-option-type/"&gt;Option type&lt;/a&gt; which either produces a &lt;code&gt;List&lt;/code&gt; of Strings representing our proteins or &lt;code&gt;None&lt;/code&gt;. This is the original goal of the exercise.&lt;/li&gt;
&lt;li&gt;An additional requirement that our solution stop consuming inputs once the appropriate output has been achieved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Importing the relevant libraries
&lt;/h2&gt;

&lt;p&gt;It turns out we only need to import the &lt;code&gt;FParsec&lt;/code&gt; library. Everything else we need is a native function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s2"&gt;"nuget: FParsec"&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;FParsec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining our domain
&lt;/h2&gt;

&lt;p&gt;Let's create some types to represent our domain space. In this case, we just need presentation of our codons and our proteins.&lt;/p&gt;

&lt;p&gt;We're going to represent our codons as two separate types, &lt;code&gt;ProteinCodon&lt;/code&gt;, which can be translated into protein amino acids, and &lt;code&gt;StopCodon&lt;/code&gt;, which represent &lt;code&gt;STOP&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ProteinCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AUG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGG&lt;/span&gt; 

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;StopCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UAA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGA&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Protein&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Methionine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tryptophan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining our helper functions
&lt;/h2&gt;

&lt;p&gt;We need a few functions to help us out here. &lt;code&gt;toProtein&lt;/code&gt; takes a &lt;code&gt;ProteinCodon&lt;/code&gt; and returns the corresponding &lt;code&gt;Protein&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;toProtein&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AUG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Methionine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUA&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCA&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tryptophan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can test that running this function works&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;toProtein&lt;/span&gt; &lt;span class="nc"&gt;UGG&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="nc"&gt;Tryptophan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining our basic parsers
&lt;/h2&gt;

&lt;p&gt;The most complex part of this is our generic pUnion parser. Without getting too much into the details, we use the FParsec functions &lt;code&gt;stringReturn&lt;/code&gt; and &lt;code&gt;choice&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.quanttec.com/fparsec/reference/charparsers.html#members.stringReturn"&gt;stringReturn&lt;/a&gt; accepts a string to parse against and a type to return and makes a Parser of that type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.quanttec.com/fparsec/reference/primitives.html#members.choice"&gt;choice&lt;/a&gt; accepts a sequence of many parsers of the same type and returns a Parser of that type.&lt;/p&gt;

&lt;p&gt;We define a helper function &lt;code&gt;pCase&lt;/code&gt; that takes a union type value and makes a parser for that value specifically, and then we map that function across all cases in a union for full coverage.&lt;/p&gt;

&lt;p&gt;Putting it all together, we've defined a parametrized parser that accepts a sum type like one of the codons and makes a parser that will compare a string to see if it's representations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;FSharp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Reflection&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pCase&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;UnionCaseInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;stringReturn&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;FSharpValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MakeUnion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[||])&lt;/span&gt; &lt;span class="o"&gt;:?&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nn"&gt;FSharpType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GetUnionCases&lt;/span&gt; &lt;span class="n"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;pCase&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus we can say &lt;code&gt;pUnion&amp;lt;ProteinCodon&amp;gt;&lt;/code&gt; and get a parser of type &lt;code&gt;Parser&amp;lt;ProteinCodon, unit&amp;gt;&lt;/code&gt;, or &lt;code&gt;pUnion&amp;lt;Protein&amp;gt;&lt;/code&gt; to get a parser of type &lt;code&gt;Parser&amp;lt;Protein, unit&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Composing our parsers
&lt;/h2&gt;

&lt;p&gt;Now we can start combining some parsers together to get what we want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProteinCodon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toProtein&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ToString&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pProteinString&lt;/code&gt; above starts with the parser for protein codons &lt;code&gt;pUnion&amp;lt;ProteinCocon&amp;gt;&lt;/code&gt; and then uses the &lt;code&gt;|&amp;gt;&amp;gt;&lt;/code&gt; operator to map the parser results to &lt;code&gt;toProtein&lt;/code&gt; and that map those value to the &lt;code&gt;ToString&lt;/code&gt; method. The result is a Parser capable of checking if a string matches a &lt;code&gt;ProteinCodon&lt;/code&gt;, but returns a string representing a &lt;code&gt;Protein&lt;/code&gt;. It's full return type is &lt;code&gt;Parser&amp;lt;string, unit&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's see what it tells us with a valid input. The run function is what we use to actually execute our parsers on some data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="s2"&gt;"AUG"&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="s2"&gt;"Methionine"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! That did exactly what we wanted. It parsed the string representing a codon, but &lt;em&gt;returned&lt;/em&gt; the value of the codon converted to a protein, converted to a string. Let's now try an invalid input. Something that shouldn't be parsable into a protein.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="s2"&gt;"UGA"&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Ln&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nc"&gt;Col&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nc"&gt;UGA&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nc"&gt;Expecting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;AUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UAC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UAU'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UCA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UCC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UCG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UCU'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UGC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UGG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UGU'&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UUA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UUC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UUG'&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UUU'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Error! or well, successful error? Our parser successfully rejected the &lt;code&gt;StopCodon&lt;/code&gt; string we passed in, and told us it was looking for a string representing a &lt;code&gt;ProteinCodon&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's make some more parsers.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pStopCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StopCodon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;%&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pStopCodon&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eof&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we make the parser for our &lt;code&gt;StopCodon&lt;/code&gt;, &lt;code&gt;pStopCodon&lt;/code&gt;. Note that &lt;code&gt;pStopCodon&lt;/code&gt; parses a &lt;code&gt;StopCodon&lt;/code&gt;, but then uses the FParsec operator &lt;code&gt;&amp;gt;&amp;gt;%&lt;/code&gt; to ignore that value and return a &lt;code&gt;unit&lt;/code&gt; instead. This is so we can combine it with the &lt;code&gt;eol&lt;/code&gt; (end of line) parser in &lt;code&gt;pStopOrEol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;|&amp;gt;&lt;/code&gt; is another &lt;code&gt;FParsec&lt;/code&gt; operator which takes two parsers and returns a parser that can be either one, so long as they're the same type. Since &lt;code&gt;eol&lt;/code&gt; returns a unit () we needed to get stop to do the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt; &lt;span class="s2"&gt;"UGA"&lt;/span&gt; &lt;span class="c1"&gt;//valid StopCodon input&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="c1"&gt;// valid "end of line" input&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt; &lt;span class="s2"&gt;"xxx"&lt;/span&gt; &lt;span class="c1"&gt;//invalid input&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Ln&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nc"&gt;Col&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;xxx&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nc"&gt;Expecting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UAA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UAG'&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;UGA'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success! Our parser successfully accepts a string that represents a &lt;code&gt;StopCodon&lt;/code&gt; or the end of a string but rejects anything else. Note that our "unit" type output from the successful parsers is returned as &lt;code&gt;&amp;lt;null&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pProteinStringList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manyTill&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we put it all together in the &lt;code&gt;pProteinStringList&lt;/code&gt; parser. Here we use the &lt;code&gt;FParsec&lt;/code&gt; function &lt;code&gt;manyTill&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;manyTill&lt;/code&gt; is a function that takes two parsers; it will continue to collect values of the first until it hits a value of the second, and then returns the values from the first as a list.&lt;/p&gt;

&lt;p&gt;This is conveniently, exactly what we need for this challenge!&lt;/p&gt;

&lt;h2&gt;
  
  
  Running our solution
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;proteins&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pProteinStringList&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;_,&lt;/span&gt; &lt;span class="o"&gt;_)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Failure&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can finally put it all together with our proteins functions which accepts a string and uses the &lt;code&gt;FParsec&lt;/code&gt; function &lt;code&gt;run&lt;/code&gt; which is what actually applies our parsers to some string.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;run&lt;/code&gt; returns a &lt;code&gt;ParserResult&lt;/code&gt; which is a &lt;code&gt;Success&lt;/code&gt; if the input was parsed without error and a &lt;code&gt;Failure&lt;/code&gt; with error messages if it doesn't. Here we're choosing to ignore all the extra meta data and just convert these to an option&amp;gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;proteins&lt;/span&gt; &lt;span class="s2"&gt;"AUG"&lt;/span&gt; &lt;span class="c1"&gt;// returns [ "Methionine" ]&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"Methionine"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;proteins&lt;/span&gt; &lt;span class="s2"&gt;"UGA"&lt;/span&gt; &lt;span class="c1"&gt;// returns []&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;proteins&lt;/span&gt; &lt;span class="s2"&gt;"AUGUCUUAGAUG"&lt;/span&gt; &lt;span class="c1"&gt;// returns [ "Methionine", "Serine" ]&lt;/span&gt;

&lt;span class="nc"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"Methionine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Serine"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. It all works. Thank you for reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's the entire solution:
&lt;/h2&gt;

&lt;p&gt;Without the comments, it's pretty concise! Most of the code is just setting up our domain! And we haven't had to define any loops, lists, maps, or finicky control logic. Our controls are baked into our data types. Yay parsers!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s2"&gt;"nuget: FParsec"&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;FParsec&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ProteinCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AUG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGU&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGC&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGG&lt;/span&gt; 

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;StopCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UAA&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAG&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGA&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Protein&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Methionine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Tryptophan&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;toProtein&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AUG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Methionine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Phenylalanine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUA&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UUG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Leucine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCA&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UCG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Serine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UAC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tyrosine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGU&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGC&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Cysteine&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;UGG&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Tryptophan&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pCase&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;UnionCaseInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;stringReturn&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;FSharpValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MakeUnion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[||])&lt;/span&gt; &lt;span class="o"&gt;:?&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nn"&gt;FSharpType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GetUnionCases&lt;/span&gt; &lt;span class="n"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;pCase&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProteinCodon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toProtein&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ToString&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pStopCodon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pUnion&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StopCodon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;%&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pStopCodon&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eof&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pProteinStringList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manyTill&lt;/span&gt; &lt;span class="n"&gt;pProteinString&lt;/span&gt; &lt;span class="n"&gt;pStopCodonOrEOL&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;proteins&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;pProteinStringList&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;_,&lt;/span&gt; &lt;span class="o"&gt;_)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Failure&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>fsharp</category>
      <category>fparsec</category>
      <category>exercism</category>
      <category>practice</category>
    </item>
    <item>
      <title>7 Tech Talks That Actually Made A Difference</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Wed, 17 Mar 2021 20:53:25 +0000</pubDate>
      <link>https://forem.com/kirkcodes/7-tech-talks-i-love-and-why-23lj</link>
      <guid>https://forem.com/kirkcodes/7-tech-talks-i-love-and-why-23lj</guid>
      <description>&lt;p&gt;When I just started learning to code I was &lt;strong&gt;very obsessed&lt;/strong&gt; and spent &lt;em&gt;far too much time&lt;/em&gt; watching software development videos.&lt;/p&gt;

&lt;p&gt;I was determined to become the Best Python Developer In The World (don't do this) and I would spend the wee hours of the morning watching programming video after programming video searching for more grains of insight (don't do this either). &lt;/p&gt;

&lt;p&gt;I wanted to learn the &lt;strong&gt;Best Way&lt;/strong&gt; to write code; the most powerful, idiomatic, robust, resilient, &lt;em&gt;elegant&lt;/em&gt; solutions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That was, in retrospect, not a bad ideal. But the way I went about it may have been a bit silly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Real working software design is about tradeoffs, and providing solutions, even when those solutions are not as elegant as we would like. And no amount of videos can replace trying your hand at solving a problem. Fortunately I learned this before it was too late.&lt;/p&gt;

&lt;p&gt;But I wouldn't call my time spent watching my contemporaries fruitless. Good developers &lt;em&gt;learn from other developers&lt;/em&gt;. Whether through videos, articles, courses, pair programming, or just perusing github repos, it's always good to weave direct learning between time in the text editor.&lt;/p&gt;

&lt;p&gt;My career is not very long nor is it very storied, but I have come across a few tech talks in my time that make a special impact on me; talks that &lt;strong&gt;changed&lt;/strong&gt; the way I wrote and thought about code, and my relationship with my profession. These talked accelerated my competency, not with niche tricks for compiler optimizations, but with sensible and down to earth explanations of goals and paradigms that resonated with me. These are not &lt;strong&gt;all&lt;/strong&gt; the talks I love; they're just the ones I've been thinking of the most recently. In each case, I cherish the person who gave them, for taking the time to try and teach me something beyond just syntax and IDEs.&lt;/p&gt;

&lt;p&gt;I've also tried as best as I can to choose talks that I believe to be &lt;em&gt;widely applicable&lt;/em&gt;, &lt;em&gt;approachable&lt;/em&gt;, and &lt;em&gt;actionable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So the best thing I can think to do to pay back these people who have shared so much with me, is to share them with you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With each talk I've added a little blurb to provide context, because if I'm going to ask you to consider another piece of content in a time &lt;em&gt;bursting&lt;/em&gt; with content, the least I can do is tell you why it was special to &lt;em&gt;me&lt;/em&gt;, and maybe those feelings might resonate with you as well.&lt;/p&gt;

&lt;p&gt;So without further ado, here are&lt;/p&gt;

&lt;h2&gt;
  
  
  7 Technical Talks I Love (and Why!)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://www.youtube.com/watch?v=DJtef410XaM&amp;amp;list=PLIYs5xFeCcq5mKWNeQfz3-9Bc6iFM_gtj&amp;amp;index=9"&gt;The Clean Architecture&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Brandon Rhoades&lt;/li&gt;
&lt;li&gt;Length: 50 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: Code architecture, Software design, Enterprise design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fifty minutes, Brandon Rhoades did for me what dozens of other examples and articles failed to achieve.&lt;/p&gt;

&lt;p&gt;He provides a sensible approach (with examples) for structuring Full Applications, with methods and reasonings that work across the board, but &lt;em&gt;especially&lt;/em&gt; for folks attempting to write modern, mature code in languages like python, ruby, and javascript.&lt;/p&gt;

&lt;p&gt;Brandon is also one of the best orators I've heard period, and it's an amazing feeling to receive a software architecture lecture but feel like you're being told a story.&lt;/p&gt;

&lt;p&gt;Highly recommend for newer developers struggling to understand how to put together larger pieces of code in greater context that one or two files or modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://www.youtube.com/watch?v=AG3KuqDbmhM"&gt;Thirteen ways of looking at a Turtle&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Scott Wlaschin&lt;/li&gt;
&lt;li&gt;Length: 1 hour and 5 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: Software Design, API design, OOP design, Functional design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've made in no secret that I love &lt;a href="https://en.wikipedia.org/wiki/Functional_programming"&gt;Functional Programming&lt;/a&gt; and &lt;a href="https://fsharp.org/"&gt;F#&lt;/a&gt; in particular.&lt;/p&gt;

&lt;p&gt;It feels almost impossible to talk about learning F# without talking about Scott Wlaschin, who's website, fsharpforfunandprofit.com has help inumerable developers, from new F# users, to other functional programmers, to anyone interested in learning how to &lt;em&gt;solve problems with software.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this talk, Scott takes you through 13 software designs all aimed at solving a single problem, highlighting apporoaches object oriented, functional, procedural, modular, and enterprise, and it's quiet the journey to travel, but I can assure that he's an excellent guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://www.youtube.com/watch?v=0yKf8TrLUOw"&gt;GOTO 2016 • Pure Functional Programming in Excel&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Felienne Hermans&lt;/li&gt;
&lt;li&gt;Length: 43 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: Spreadsheets are code, Prototyping, Inspiration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oh no, another functional programming talk!&lt;/p&gt;

&lt;p&gt;But wait, Excel? Is that even programming?&lt;/p&gt;

&lt;p&gt;Yes it is. That's kind of the point. In about 40 minutes Felinne Hermans delivers a delightful deep dive in doing deep work in Excel. Her passion is infectious, and engaging, and if nothing else, it's wonderful to see someone who seems to genuinely &lt;em&gt;care&lt;/em&gt; and &lt;em&gt;love&lt;/em&gt; the work they are doing.&lt;/p&gt;

&lt;p&gt;But there's much more to this talk, and this may be giving it all away, but this talk is a great reminder for me that &lt;em&gt;programming&lt;/em&gt; is all about using software to deliver solutions. Too often developers get caught up in their own hype and Felinne reminds us that there is expertise to be had in all places, and it's worth learning those tools that power the world around us.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://www.youtube.com/watch?v=YklKUuDpX5c&amp;amp;list=PLIYs5xFeCcq5mKWNeQfz3-9Bc6iFM_gtj&amp;amp;index=4"&gt;The Naming of Ducks: Where Dynamic Types Meet Smart Conventions&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Brandon Rhoades&lt;/li&gt;
&lt;li&gt;Length: 30 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: Naming conventions, semantic design, code as documentation, Variable naming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Brandon's back! It may seem odd to have the same person twice on a list of seven but what you have to understand is I love &lt;em&gt;all&lt;/em&gt; of Brandon's talks and half of the time working on this was trying to narrow them down.&lt;/p&gt;

&lt;p&gt;If I could call "The Clean Architecture" a talk about high level software strategy, "The Naming of Ducks" is a talk about &lt;em&gt;tactics&lt;/em&gt;; battle testing strategies to maintain a sense of control in a growing codebase, &lt;em&gt;especially&lt;/em&gt; in languages where you can't rely on explicit types, like python and javascript.&lt;/p&gt;

&lt;p&gt;This talk is another I highly recommend for newer developers who plan on writing code that is &lt;strong&gt;read by other people&lt;/strong&gt; (including yourselves in the future).&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://www.youtube.com/watch?v=IcgmSRJHu_8&amp;amp;t=1s"&gt;Making Impossible States Impossible&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Richard Feldman&lt;/li&gt;
&lt;li&gt;Length: 25 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: Refactoring, Reducing Errors, Functional Design, Static Typing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I had to suggest &lt;strong&gt;just one&lt;/strong&gt; video from this list for anyone to watch, it would be this one.&lt;/p&gt;

&lt;p&gt;Making Impossible States Impossible is a talk that aligns with my very core values of good software design.&lt;/p&gt;

&lt;p&gt;The presenter, Richard Feldman, is one of the chief evangelists of the &lt;a href="//elm-lang.org/"&gt;Elm programming language&lt;/a&gt; which remains my favourite way to write front-end code. In the talk, Richard suggests how to make code more resilient by using the power of our software &lt;em&gt;domains&lt;/em&gt;; the types and values we construct our applications around, to create code robustness that goes beyond even the need for powerful tests. Because Richard argues that with the right design, you won't even need the tests at all. A very tactical talk.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;a href="https://www.youtube.com/watch?v=TqfbAXCCVwE"&gt;Building Resilient Frontend Architecture&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Monica Lent&lt;/li&gt;
&lt;li&gt;Length: 35 minutes&lt;/li&gt;
&lt;li&gt;Key Themes: FrontEnd Architecture, Resiliency, Legacy Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping up with the theme of power in the front-end, we head back into the realm of strategy, context, and understanding. &lt;/p&gt;

&lt;p&gt;Monica Lent delivers a powerful and engaging narrative about how we design front end applications, and why we write the code that we write. In just 30 minutes she manages to weave the concepts of technical debt, architectural patterns, API design, and effective communication and it just comes together leaving you feeling almost &lt;em&gt;refreshed&lt;/em&gt; at the thought of using the context she provides to deliver higher-quality, less stressful applications.&lt;/p&gt;

&lt;p&gt;Great for all but especially front-end folks out there.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;a href="https://www.youtube.com/watch?v=6avJHaC3C2U&amp;amp;t=26s"&gt;The Art of Code&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Presenter: Dylan Beattie&lt;/li&gt;
&lt;li&gt;Length: 1 hour&lt;/li&gt;
&lt;li&gt;Key Themes: Whimsy and Delight, Inspiration, Language Design, Code Philosophy, Pop culture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And last but not least, we have the art of code.&lt;/p&gt;

&lt;p&gt;I honestly am not going to say too much about this one because I don't want to spoil the surprise, but I will say that for many of you, this talk will remind you &lt;em&gt;why you got into code.&lt;/em&gt; For others it might be great insight into &lt;em&gt;why do other people get into code.&lt;/em&gt; But for everyone it should be an amazing, illuminating, magical ride.&lt;/p&gt;

&lt;p&gt;Don't try and multitask this one. Take the hour, have some fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope these provide some value to you. I hope they give you ideas. I hope they give you inspiration. If they do, let me know, I'm dying to talk about these with someone. If you hate them, let me know too. There's probably more I need to learn.&lt;/p&gt;

&lt;p&gt;Until then,&lt;br&gt;
Kirk&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>resources</category>
      <category>development</category>
      <category>strategy</category>
    </item>
    <item>
      <title>Database Security Checklist for Small Teams</title>
      <dc:creator>Kirk Shillingford</dc:creator>
      <pubDate>Wed, 17 Mar 2021 19:53:46 +0000</pubDate>
      <link>https://forem.com/arctype/database-security-checklist-for-small-teams-2mhj</link>
      <guid>https://forem.com/arctype/database-security-checklist-for-small-teams-2mhj</guid>
      <description>&lt;p&gt;15 minute read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Acknowledging Risk&lt;/li&gt;
&lt;li&gt;Understanding the principal of low hanging fruit&lt;/li&gt;
&lt;li&gt;Creating a security policy&lt;/li&gt;
&lt;li&gt;Server Security&lt;/li&gt;
&lt;li&gt;Email attackers&lt;/li&gt;
&lt;li&gt;User Roles and Permissions&lt;/li&gt;
&lt;li&gt;Data Sanitizing&lt;/li&gt;
&lt;li&gt;Request Throttling&lt;/li&gt;
&lt;li&gt;Physical Security to Augment Digital Steps&lt;/li&gt;
&lt;li&gt;Self Reflection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@itsliamtucker?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Liam Tucker&lt;/a&gt; on &lt;a href="/s/photos/security?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg22tns797vtm2v3dvm3f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg22tns797vtm2v3dvm3f.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi, my name is &lt;a href="https://www.github.com/tkshill" rel="noopener noreferrer"&gt;Kirk&lt;/a&gt;. I’m a full stack software developer working on the .NET ecosystem and managing a large &lt;a href="https://www.sqlservertutorial.net/getting-started/what-is-sql-server/" rel="noopener noreferrer"&gt;SQL Server&lt;/a&gt; database.&lt;/p&gt;

&lt;p&gt;I wrote this post to try to answer some of my own questions about what modern database security in 2021 looks like, especially if you’re in the tech field and looking into creating or supporting your own database management system.&lt;/p&gt;

&lt;p&gt;While the scenarios discussed can be applicable to a wide variety of domains and specialities, most of the examples will pertain to web, web accessible applications, and those with self-hosted servers.&lt;/p&gt;

&lt;p&gt;At the time of writing this (early 2021), the COVID-19 pandemic has decimated most of the world’s ability to freely travel, and thus there’s been a &lt;a href="https://www.digitalcommerce360.com/2021/02/15/ecommerce-during-coronavirus-pandemic-in-charts/" rel="noopener noreferrer"&gt;sharp up-tick&lt;/a&gt; in the creation and desire for online solutions. Developers has mobilized to create a variety of web stores, app portals, and even SMS-based platforms to meet the needs of clients without requiring them to visit in person stores.&lt;/p&gt;

&lt;p&gt;But with a rise in both product and service availability online, and demand from consumers, we should also expert a rise in malicious actors willing to exploit the system for personal gain. &lt;a href="https://www.ratchetandwrench.com/articles/10559-the-rise-and-rise-of-cybercrime" rel="noopener noreferrer"&gt;Cyber crime is on the rise&lt;/a&gt;. The year 2020 saw a marked increase in online criminal activity in the order of billions of dollars in costs to businesses, not to mention the consequences of serious data breaches for consumers.&lt;/p&gt;

&lt;p&gt;So let’s dive right in.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Acknowledge the Risk of Digital Business &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Photo by Loic Leray at Unsplash&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mpb117e8s5xfmvxd8ju.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mpb117e8s5xfmvxd8ju.jpg" alt="Man walking on tightrope over canyon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may sound paranoid to say, but I genuinely think that everyone should approach software development in 2021 with the approach that bad actors will make at least some attempt to compromise your operations. Some studies estimate that the &lt;a href="https://www.accenture.com/us-en/insights/security/cost-cybercrime-study" rel="noopener noreferrer"&gt;average cost of cyber attacks&lt;/a&gt; on business is up to $2.6 million.&lt;/p&gt;

&lt;p&gt;Unfortunately, the more successful your business becomes, and the more notoriety you gain, the greater the chances that you’ll receive unwanted notice from cyber-criminals, whether as part of some wide scale attack, or specific intent.&lt;/p&gt;

&lt;p&gt;“I’m too small to be targeted,” is a phrase you might say to yourself.&lt;/p&gt;

&lt;p&gt;Let’s swiftly get that notion out of our minds.&lt;/p&gt;

&lt;p&gt;Like real life thefts and ransoms, being small makes you more likely to be targeted, not less. Your average thief does not rob multi-million dollar houses; the risk reward profile makes small to medium sized businesses more attractive. &lt;/p&gt;

&lt;p&gt;They tend to have much worse security to prevent attack, and less resources to combat an attack after it’s happened.Plus, since this is all digital, your average malicious entity would much rather deploy ransomware on hundreds of small to medium sized businesses, than chase a big whale that had the potential to bring down their operation. &lt;a href="https://www.eteam.io/blog/targets-for-cyber-criminals-2018" rel="noopener noreferrer"&gt;Growing business are extremely vulnerable&lt;/a&gt; and should always place themselves in a high risk category.&lt;/p&gt;

&lt;p&gt;“The question isn’t, ‘Are there bears nearby?’ There’s definitely bears nearby. That’s just the price to pay for coming to the woods. They’re here and there’s nothing you can do about it. Your job is just to make it as hard as possible for them to get you while you’re here.”&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understand the principle of low hanging fruit &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.redd.it%2Fx8gps6babxnz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.redd.it%2Fx8gps6babxnz.jpg" alt="Men running from a charging bear. One has tripped. He is doomed."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This photo isn't real, but it got my point across way too well not to use it. &lt;/p&gt;

&lt;p&gt;You don’t need to be the first guy, but you definitely don’t want to be the last guy.&lt;/p&gt;

&lt;p&gt;While I’d love to be able to report that a perfect defense exists, and some combination of money and technology can keep you 100% safeguarded, but unless your entire business lives in a safe that you never open, that’s just not the case.&lt;/p&gt;

&lt;p&gt;What I learnt is rather than try and create some perfect, impregnable system, your time is better spent following a &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle" rel="noopener noreferrer"&gt;Pareto Principle&lt;/a&gt; approach; an iterative process where you continuously adopt the best solutions for your setup, balance cost and expense vs effect.&lt;/p&gt;

&lt;p&gt;The picture above, while hilarious, perfectly illustrates the type of environment we’re dealing with in today’s digital society:&lt;/p&gt;

&lt;p&gt;the bear (cyber-attackers), are faster and stronger than you are. Attackers will always be one step ahead of defenders. As defenders, we can only react and guarded against the threats we know. Attackers are constantly creating threats we Don’t know. Once a new threat is discovered, we scramble to fix things before it’s too late. Sometimes we’re successful, sometimes we aren’t.&lt;/p&gt;

&lt;p&gt;As morbid as it sounds, your goal isn’t to be most secure platform in the world; it’s just to be &lt;strong&gt;the least, attractive target for attack.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike getting picked as someone’s pacing buddy on the annual company hike, you never want to be a hacker’s first choice. Attacks are best experienced vicariously; we watch when they happen to others and make sure it doesn’t happen to us.&lt;br&gt;
What does best solution mean? I tend to break it down with the following statement;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;“What is the cheapest solution (in terms of cost, development cycles, dev op hours, troubleshooting, etc) to move a vulnerability in my system one tier down from where it currently exists.”&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I tend to classify my risks in to three categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Critical Weaknesses&lt;/strong&gt;: Obvious, easily exploitable weaknesses that could instantly bring down your organization or result in a data breach. These are also things that are easily discoverable. Invalid/Non existent security certifications, unsafe form validation, open API access. Every day these continue to exist you enterprise is moments away from an unrecoverable failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Medium Risk&lt;/strong&gt;: These are the types of problems that are looming threats, and could easily escalate if left unchecked. Exposed/Unrestricted database access within the network,  weak passwords for sensitive data, lack of firewall/antivirus software for your servers. They may not seem like immediate problems, but are essentially ticking time bombs, and it’s still a matter of when, not if, that you’ll regret not addressing them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Low Risk&lt;/strong&gt;: This is where you’ve covered all the basics, and you’ve basically got a few holes left in your system for rare events. Should you address these at some point? Yes. But nothing here should be an open door and would either require a large amount of insider knowledge or effort on the side of the attacker.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So your strategy becomes dealing with critical and medium weaknesses as quickly as possible and not falling into a fall sense of security because you’ve done a bunch of updates to low risk issues. It doesn’t matter if you’ve got the best home security system money can buy if you’ve left your door open.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You Should Have A Security Policy &lt;a&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Photo by Scott Graham at Unsplash&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1450101499163-c8848c66ca85%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDJ8fGRvY3VtZW50fGVufDB8fHx8MTYxNTU5OTk0NQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1450101499163-c8848c66ca85%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDJ8fGRvY3VtZW50fGVufDB8fHx8MTYxNTU5OTk0NQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Man writing important docs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edited out of this image are the tears the security admin shed at having to write more that two pages of text.&lt;/p&gt;

&lt;p&gt;You should have a security policy. That’s it, that’s the tweet. Every business or product should have a security policy. There’s lots of &lt;a href="https://www.computerworld.com/article/2572970/10-steps-to-a-successful-security-policy.html" rel="noopener noreferrer"&gt;good resources&lt;/a&gt; on how to make one, but any policy you make needs to secure the bare minimum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What data do we collect and how much security does it require (credit card info needs lots of security, favourite power ranger, not so much)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Where do we keep our data and how difficult is it to access?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who has access to what parts of the system?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do we expose to the outside and through what channels do we expose it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What 3rd party applications do we depend on and how secure do we think those are?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's my company’s risk profile?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The more data you collect, the higher your risk profile&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The more users you have, the higher your risk profile&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Financial, Health, and location data are especially high risk&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Secure the Internal Network &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Photo by Markus Spiske at Unsplash&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1581700305899-b7ccfcc7ff6f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDM3fHxsb2NrZWR8ZW58MHx8fHwxNjE1NjAwMDMy%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1581700305899-b7ccfcc7ff6f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDM3fHxsb2NrZWR8ZW58MHx8fHwxNjE1NjAwMDMy%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Locked barn door"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we’ve talked about earlier, the best security is a black box; a network completely isolated from external networks (and the internet) is the only true way to prevent attacks via that vector.&lt;/p&gt;

&lt;p&gt;Unfortunatly, your data doesn’t exist in isolation. Even if it has no direct connections, if your database and DBMS live on a network with internet access, then your data is somewhat exposed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep your databases &lt;a href="https://www.upguard.com/blog/11-steps-to-secure-sql" rel="noopener noreferrer"&gt;hidden on the network&lt;/a&gt;. No user who doesn’t need access to the DB should even be able to perceive it on the company network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limit the ports that can access your database server (this shuts down a large swath of potential attack vectors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be aggressive in your firewall usage for your critical data. Always follow the principal of minimal access. Every port and connection should be closed unless you explicitly open it. &lt;strong&gt;Every request should be untrusted unless specifically trusted. Every user should be permissionless unless explicitly granted permission&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. It’s Probably Going to Be an Email &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Photo by Stephen Phillips at Unsplash&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1557200134-90327ee9fafa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDJ8fGVtYWlsfGVufDB8fHx8MTYxNTYwMDA2Ng%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1557200134-90327ee9fafa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDJ8fGVtYWlsfGVufDB8fHx8MTYxNTYwMDA2Ng%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Image of an email inbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we get too deep, I need to note that you can do all the protections in the world, but &lt;em&gt;the majority of cyber attacks still come from &lt;em&gt;&lt;a href="https://digitalguardian.com/blog/phishing-attack-prevention-how-identify-avoid-phishing-scams" rel="noopener noreferrer"&gt;basic phishing attacks&lt;/a&gt;&lt;/em&gt; through email.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Anyone in your organization who willingly clicks a link to a malicious website or downloads an attachment from an unrecognized source has the capability to introduce malware and ransomware to the machine they used to access that link.&lt;/p&gt;

&lt;p&gt;Beyond setting up limitations on downloads for browsers on work machines, the best you can do is educate all your users on proper email safety practices.&lt;/p&gt;

&lt;p&gt;Always check to ensure you’re receiving emails from a qualified sender (I highly suggest using tools that can identify addresses that operate in the same user group as yours).&lt;/p&gt;

&lt;p&gt;A common phishing tactic is to create an address that closely mimics one within your network, e.g. &lt;code&gt;kirk@ournotwork.com&lt;/code&gt; vs &lt;code&gt;kirk@ournetwork.com&lt;/code&gt;, with the attacker hoping you will download and run the attached malware before you notice that that address actually isn’t valid. Be vigilant.&lt;/p&gt;

&lt;p&gt;Once a user has downloaded something design to compromise the network, that’s where our safeguards in part one can kick in to ensure that the most that can happen is that files on the local machine are the only ones at risk and the rest of the company network (especially our key database stores) remain safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Server Roles, Permissions and Access &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Photo by Mark Leishman at Unsplash&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1561754435-d5288c2c5afa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDQzfHxndWFyZHxlbnwwfHx8fDE2MTU2MDAxMTg%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1561754435-d5288c2c5afa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDQzfHxndWFyZHxlbnwwfHx8fDE2MTU2MDAxMTg%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="British Royal guards standing at attention"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I said earlier, one of the primary purposes of this article is to help folks who create, maintain and utilize database management systems, especially those of us who has to store sensitive user data. Once someone has managed to breach your firewalls and network permissions, the final layer is your DBMS itself. Similar to the rules in safeguarding your network, you want to be hyper specific in what access your server allows. Most DBMS systems allow you to fine tune exactly what each authorized user is allowed to do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a general rule, no one but the system administrator should have full permissions on the system.&lt;/li&gt;
&lt;li&gt;Enforce strict password policies but avoid the common pitfall of having such frequent password overturn that users start being lazy about their password choices.&lt;/li&gt;
&lt;li&gt;Create dedicated profiles for any apps or services that have access to your database.&lt;/li&gt;
&lt;li&gt;When possible, always use stored procedures or other predefined query systems. Do not let any user have the ability to make unrestricted queries to the database.&lt;/li&gt;
&lt;li&gt;Periodic backups are key. Automated backups. Telling yourself that you (or whoever is in charge of the db) will remember to do manual backups is a falsehood.&lt;/li&gt;
&lt;li&gt;Ensure that all your backups are Not kept on the same server instance as the main database. This completely defeats the purpose of the backups.&lt;/li&gt;
&lt;li&gt;Backup automation should be one way; getting data back from deep backups should be something that at the very least requires an explicit trigger from your system administrator/security specialist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. For The Love of User Safety, Sanitize Your Data &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Photo by JESHOOTS.COM at Unsplash&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1563453392212-326f5e854473%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fGNsZWFuaW5nfGVufDB8fHx8MTYxNTYwMDE4Mg%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1563453392212-326f5e854473%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fGNsZWFuaW5nfGVufDB8fHx8MTYxNTYwMDE4Mg%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="someone spraying some cleaning agent"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any data coming in from external sources should be treated as a potential vector for attack. Under no circumstances should you ever return raw input from your forms and web views into  your database. Typical strategies for ensuring the right data makes it to your application involve a mix of sanitizing, hashing, and streamlining. I want to highlight some of the most common ones below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sanitize your inputs. This means ensuring that the text your users type in is free of any erroneous or malicious text that might compromise your system (or just be invalid data). You have the option of sanitizing inputs in your front end code immediately in the handlers for input elements; you can also do in your web server. My suggestion; do both. Things to typically guard for:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SQL injection by adding commands that can be executed by an sql based db:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;null and oversized strings&lt;/li&gt;
&lt;li&gt;strange symbols and special characters&lt;/li&gt;
&lt;li&gt;Anything that could be interpreted as a path/file extension/internal command&lt;/li&gt;
&lt;li&gt;Do not let unqualified strings pass from your users keyboards to your database. You will regret it.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Use stored procedures - A stored procedure is a pre-written sql procedure or query that can be called by a user/service, and can work as an api to your DBMS. Rather than allow your application to pass queries directly to your database, you can allow your app access to stored procedures only, sealing up the apps ability (or anything impersonating the app) to ever issue rogue requests to the server.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Hash sensitive data - Do not store raw passwords in your database. This is another “that’s the tweet moment.” The best way to keep user data from being compromised is to Not Store It. The second best way is to use various hashing, salting, and encryption  techniques to make sure that if anyone does get access to data they shouldn’t, they can’t actually use it.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Store Less Data&lt;/strong&gt; - Yes, you heard me. Store less data. I get it, storage is cheap nowadays and we all feel like not keeping every bit of data our users are willing to give up is leaving money on the table, but you should always be weighing the risk vs reward of storing sensitive user data. Maybe you don’t need to store data you don’t currently need as a “just in case”. The less data you keep, the less of a target on your back.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Request Throttling Works &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Photo by Jay R of Unsplash&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1612181345252-485e25c59eb2%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDIxfHxzcGVlZG9tZXRlcnxlbnwwfHx8fDE2MTU2MDAyNDQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1612181345252-485e25c59eb2%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDIxfHxzcGVlZG9tZXRlcnxlbnwwfHx8fDE2MTU2MDAyNDQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" alt="speedometer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DDOS (&lt;a href="https://apiacademy.co/2019/11/denial-of-service-attacks-on-the-rise/" rel="noopener noreferrer"&gt;Distributed Denial of Service&lt;/a&gt;) attacks suck. Without getting into the details, DDOS attacks involve bombarding a server with an overwhelming amount of requests, which can cause the server to crash, or break in cryptic ways, accidentally revealing data that should not be available to the attacker. It can also be used to hold an organization hostage, as typically regular users are unable to use the API while it is under attack.&lt;/p&gt;

&lt;p&gt;And if you haven’t been paying attention to cybersecurity news recently, DDOS attacks are on the rise, both in frequency, and in severity. The original attacks sent a few hundred requests per second. Currently tech employed by bad agents allow them to send millions of requests per second. DDoS attacks can happen at any time, and there’s not much you can do to stop the attack from happening. But there are strategies to stop the attack from harming you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nordicapis.com/everything-you-need-to-know-about-api-rate-limiting/" rel="noopener noreferrer"&gt;Request throttling&lt;/a&gt; refers to purposefully limiting the rate of requests your servers process at any given time, and can be a good tactic to prevent and limit the damage of DDOS attacks. Many hosting platforms have anti DDoS policies and methods and it’s worth spending some time finding a host prepared to defend against such attacks, and if self hosting, having a good strategy can save a lot of heartache in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Physical Security Helps Too &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Photo by Yue Su on Unsplash&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1597890698604-d40f50ff8a23%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDQ5fHxmcnVpdCUyMHRyZWV8ZW58MHx8fHwxNjE1NjAwNDAx%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1597890698604-d40f50ff8a23%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDQ5fHxmcnVpdCUyMHRyZWV8ZW58MHx8fHwxNjE1NjAwNDAx%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" alt="Low hanging fruit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ultimately, developers are people. People make mistakes. People have deadlines and stressors and we get tired. Most, if not all of us want to be a good job, but we can’t let to help some subtle things slip by the wayside. So I think it’s always good to go over the small quick wins that can avoid egg-on-face moments down the line.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.infotech.co.uk/blog/why-your-business-desperately-needs-a-password-policy" rel="noopener noreferrer"&gt;Strong password policy&lt;/a&gt; - There’s no excuse for weak password policies in 2021. And please opt for stronger password vs frequently changing ones. I find users bristle at 3 month password changes and begin to find ways to subvert the system. 6-12 months seems ideal but ultimately longer passwords are better passwords.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limit jump drive usage on work machines. If this isn’t already a policy at your organization you may get a lot of push back. It’s worth pressing on though. Jump drives are error-prone at best and a vehicle for espionage and malicious software at worst. For employees that truly need to access work from outside their designated machines, allow secure ssh sessions before copying onto external storage devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related to above, &lt;strong&gt;do not let employees use personal computers to access the server&lt;/strong&gt;. The risk is almost never worth the reward. C suite employees tend to push back on this the most. Attempt to hold strong. You have almost zero control over what happens once a personal machine has access to sensitive data. They could already be compromised. Again, use secure ssh based channels for file access, not file transfer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not do indefinite logons. In the recent Capital riots, images showed the attackers observing unsent emails and other sensitive documentation left available on the machines of government employees. Devices left unattended should log out inactive users sooner rather than later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access tracking and logs. There should always be a record of what users are active at what times, the data they request, and the changed they make to the system. Even in benign circumstances, this can prove useful.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the actions just described are relatively easy to implement, but combined seal of many of the less glamorous ways that servers and databases get compromised. It’s the type of work that can pay dividends in the long run and great bang for your buck in terms of effort vs reward. I highly encourage anyone who cares about database security to check off some of these boxes.&lt;/p&gt;

&lt;p&gt;*A small note on privacy. Others may disagree, but I personally believe that employees shouldn’t keep secrets while on company hardware. In that vein, I think companies have zero business tracking employee actions outside of designated work environments. Company emails and company file and process access are within the purview of company security and risk mitigation. Employee’s homes, and personal habits in their lives are not. Keep the lines and distinctions clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Take Care of Yourself Too &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Photo by Andre Mouton on Unsplash&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1531989417401-0f85f7e673f8%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDl8fG1pcnJvcnxlbnwwfHx8fDE2MTU2MDEzMDc%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1531989417401-0f85f7e673f8%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDl8fG1pcnJvcnxlbnwwfHx8fDE2MTU2MDEzMDc%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D1000" alt="Monkey staring at itself in the mirror"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I want to spend some time on what is often enough the biggest weakness in an organization’s security; the security admin themselves.&lt;/p&gt;

&lt;p&gt;It is terrifying how often I see security experts apply all the following rules to everyone but themselves.&lt;/p&gt;

&lt;p&gt;We see the news of companies and organizations that get hit and all publicly shake our heads and say, “could never be me”.&lt;/p&gt;

&lt;p&gt;But most likely it could. And most likely it will. Knowledge and effort can go a long way, but a dash of humility doesn’t hurt either.&lt;/p&gt;

&lt;p&gt;Write your processes down. Designate a secondary for your critical operations. Prepare a plan in case of your sudden illness. Never assume you have all the answers, and never stop learning.&lt;/p&gt;

&lt;p&gt;Most importantly, be kind to yourself and those around you. It’s never been harder to keep information safe and secure; we’re all just trying to do our best.&lt;/p&gt;

&lt;p&gt;Hopefully this article can give folks a solid starting point to assess themselves and their organizations.&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>security</category>
      <category>database</category>
      <category>systems</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
