<?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>DEV Community: Hayden Rear</title>
    <description>The latest articles on DEV Community by Hayden Rear (@haydenrear).</description>
    <link>https://dev.to/haydenrear</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%2F1052315%2F4c17b293-9dfd-4f60-996b-b090ab8afa18.png</url>
      <title>DEV Community: Hayden Rear</title>
      <link>https://dev.to/haydenrear</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haydenrear"/>
    <language>en</language>
    <item>
      <title>Decoupling Behavior and Data</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Sat, 12 Jul 2025 18:33:10 +0000</pubDate>
      <link>https://dev.to/haydenrear/decoupling-behavior-and-data-2ble</link>
      <guid>https://dev.to/haydenrear/decoupling-behavior-and-data-2ble</guid>
      <description>&lt;p&gt;-- written by ChatGPT - edited by me --&lt;/p&gt;

&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;Extensibility of logic is always difficult. How do we add a particular case in an algebra? How do we handle the control flow? We can't use goto, and sometimes we end with callback hell with monadic styles. So what are we left with? We want a data-oriented programming design - this provides us with the ability to reason about the code easily, because of the fact that it's discrete. But then we always have the undefined nature of recursion, something Nasa thought is dangerous as it's hard to reason about stopping conditions. The AI is very good at math, and coding is getting there, but how can we make our code more logical, more algebraic, and get a recursive style for free, without the complexity?&lt;/p&gt;

&lt;p&gt;At first I thought free monads another crazy idea from the academic side. But then, once you think about it within the context of what's been happening in databases, decoupling storage and compute, you start to realize it's more a natural extension of a paradigm shift that's happening. Once you understand what a free monad is, the intuition of it, you realize there are places where the ability to reason about and extend the code increases. It fits very nicely within the greater paradigm shift of code as data, and you get reusability at yet another level. In this case, maybe the experts are right!&lt;/p&gt;

&lt;h1&gt;
  
  
  Declarative Algebras, One-Step Execution, and the Hidden Free Monad
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Describe first, act later.&lt;/strong&gt;&lt;br&gt;
Capture intent as data, postpone behavior to a pluggable interpreter—then watch extensibility emerge.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. The principle
&lt;/h2&gt;

&lt;p&gt;Across cloud warehouses, build pipelines, and micro-services, the winning pattern is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Capture &lt;em&gt;intent&lt;/em&gt; as plain data&lt;/strong&gt; – inspectable, serializable, versionable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defer &lt;em&gt;behavior&lt;/em&gt; to a separate phase&lt;/strong&gt; – interpret, optimize, simulate, or replay whenever you like.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A fancy name for that pattern—one we won’t reveal until the very end—is the &lt;em&gt;free monad&lt;/em&gt;.&lt;br&gt;
But let’s get there step by step.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Build an extensible algebra
&lt;/h2&gt;

&lt;p&gt;Start with &lt;strong&gt;zero side effects&lt;/strong&gt;. Each constructor is &lt;em&gt;frozen intent&lt;/em&gt; plus “what to do next.”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Java 21 sealed algebra of document operations&lt;/span&gt;
&lt;span class="n"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DocOp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;permits&lt;/span&gt; &lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;           &lt;span class="c1"&gt;// carry on with file text&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DocOp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// pure transform&lt;/span&gt;
    &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;           &lt;span class="c1"&gt;// carry on with new text&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DocOp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;                                               &lt;span class="c1"&gt;// nothing to pass along&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DocOp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need a new feature tomorrow—say &lt;code&gt;NotifySlack&lt;/code&gt;? Add one more &lt;code&gt;record&lt;/code&gt;; the compiler makes you handle it explicitly.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Stitch steps &lt;em&gt;declaratively&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;We need a container that chains these atoms without running them.&lt;br&gt;
Here’s a micro-“script” type (a tiny free monad):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* A finished program */&lt;/span&gt;
  &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Pure&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/* One pending step followed by the rest */&lt;/span&gt;
  &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;
      &lt;span class="nc"&gt;DocOp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cont&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pure&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/* Declarative bind */&lt;/span&gt;
  &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Pure&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;k&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;new&lt;/span&gt; &lt;span class="nc"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write workflows &lt;em&gt;as data&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;build&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;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/doc.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Script:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;String:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Script:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"dist/doc.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still no I/O!&lt;/p&gt;




&lt;h2&gt;
  
  
  4. One-step interpreter: &lt;strong&gt;jump, return, repeat&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;F&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Production engine using async I/O */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IOEngine&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concurrent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concurrent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                               &lt;span class="c1"&gt;// ← single tail-rec loop&lt;/span&gt;
      &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Pure&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;            &lt;span class="c1"&gt;// ① finished&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concurrent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completedFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&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="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                          &lt;span class="c1"&gt;// ② match the case&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thenCompose&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="o"&gt;))));&lt;/span&gt; &lt;span class="c1"&gt;// ③ jump&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&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="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
              &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;                             &lt;span class="c1"&gt;// loop continues&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&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;c&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thenCompose&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nxt&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Peel one &lt;code&gt;Step&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle the matching constructor&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return the &lt;em&gt;next&lt;/em&gt; &lt;code&gt;Script&lt;/code&gt;&lt;/strong&gt; (or tail-recurse).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That short “jump-to-next-step” loop &lt;strong&gt;never changes&lt;/strong&gt;—add new cases, plug them in, done.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Recursive composition for free
&lt;/h2&gt;

&lt;p&gt;Because every step &lt;em&gt;returns another script&lt;/em&gt;, scripts compose like Lego:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readClean&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;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"in.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Script:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;String:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Script:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;Script:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;saveTwice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;readClean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"out.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;    &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"backup.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No matter how deep the graph, the interpreter still just &lt;strong&gt;peels one layer, does work, repeats&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Why step-at-a-time rocks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Comes from “handle one step, return the rest”&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infinite pausing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You can pause, inspect, rewrite, or migrate mid-script.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fine-grained billing/retry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Each node is an observable unit of work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hot-swappable engines&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same script runs on I/O, mocks, audit logs, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local reasoning &amp;amp; changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add/adjust a constructor; compiler forces local updates.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  7. The hidden reveal
&lt;/h2&gt;

&lt;p&gt;If the structure feels familiar—a &lt;em&gt;functor&lt;/em&gt; of single actions wrapped in a bindable container—you’ve secretly rebuilt &lt;strong&gt;the free monad&lt;/strong&gt; for &lt;code&gt;DocOp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the next time you separate &lt;em&gt;intent&lt;/em&gt; from &lt;em&gt;effect&lt;/em&gt;, remember:&lt;br&gt;
that jump-to-next-step interpreter is the categorical machinery that makes &lt;strong&gt;modular, recursive, endlessly extensible&lt;/strong&gt; software almost trivial.&lt;/p&gt;

&lt;p&gt;Happy decoupling!&lt;/p&gt;

</description>
      <category>functionalreactiveprogramming</category>
      <category>functional</category>
      <category>dataorientedprogramming</category>
      <category>java</category>
    </item>
    <item>
      <title>Emergent Software Principles I've Learned</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Sat, 11 Jan 2025 20:41:16 +0000</pubDate>
      <link>https://dev.to/haydenrear/emergent-software-principles-ive-learned-2pef</link>
      <guid>https://dev.to/haydenrear/emergent-software-principles-ive-learned-2pef</guid>
      <description>&lt;h1&gt;
  
  
  Code as Data and Data Structure as a Program
&lt;/h1&gt;

&lt;p&gt;The best code is provably correct, and the most provably correct code is a data structure. Trying to write your program as a data structure makes it more testable and more provably correct. Moreover, using the best data structure for the job makes the code much more resilient and a source of great abstraction. Learn your data structures and then learn them again, always be learning your data structures! You can always start with an off-the-shelf version and then create a customized version as a performance optimization. Then you can compare the naive version to the custom version.&lt;/p&gt;

&lt;p&gt;Example: using a trie for file paths, using a graph for program analysis.&lt;/p&gt;

&lt;h1&gt;
  
  
  MicroBench
&lt;/h1&gt;

&lt;p&gt;Typically test based development (basically all development) leads to code that just barely passes. So then when you increase the load a little bit (or add just a little bit more data), it could break. This is the importance of micro-benchmarking.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scalability as Smallest Units of Work Under Infinite Load - Theory of Constraints
&lt;/h1&gt;

&lt;p&gt;Anything can break under sufficient load. Make sure that the bottleneck scales for the load you need.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pascal's Triangle as Emergent Refactors
&lt;/h1&gt;

&lt;p&gt;When I first learned recursion I spent hours banging my head against the wall implementing pascal's triangle. Later on I learned that much of emergent refactors resemble some n-dimensional version of pascal's triangle. As we refactor to add a needed emergent layer of abstraction, that layer of abstraction becomes the next layer in the base of this n-dimensional "pyramidal" structure. Make sure the layers are firm foundations for the next layer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Result Type as Point of Coupling - Decoupling Away "Distributed" as Metadata
&lt;/h1&gt;

&lt;p&gt;Typically developers depend on some stream or IO provided by some other developer, making it hard to decouple the implementation. As microservices are refactored away, result types will become more important.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Weakest Chain in the System Should be You - Observability Matters
&lt;/h1&gt;

&lt;p&gt;If you're system doesn't provide a mechanism to observe the issue before it becomes a problem, then there's something wrong with the way you deploy code.&lt;/p&gt;

&lt;p&gt;Example: before you release your code, you look through all of the errors you had - from the perspective of structured logging. So then you see the error - you ignore it. But it's not an ignorable error! In this case you made a mistake. But the system for letting you know that there is a bug is good!&lt;/p&gt;

&lt;h1&gt;
  
  
  Defining things only in terms of the most complex case, the programmer's dilemma
&lt;/h1&gt;

&lt;p&gt;The programmers dilemma is I want to do the least amount possible but I need an emergent design out of the most complex set of cases for the minimum viable product.&lt;/p&gt;

&lt;p&gt;This is coming from a greater truth related to the resilience of a system being based on the maximum amount of testing done, and the way the testing relates to the provable resilience of the system... resulting in failures when you push &lt;strong&gt;just a little bit harder&lt;/strong&gt;, just a little bit beyond what you've tested before, and specifically how that test relates to the provable resilience of the system.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Single Unifying Thread
&lt;/h1&gt;

&lt;p&gt;The most generic implementation, typically ByteBuf or something similar in IO, for instance. It should be the emergent data structure from the emergent design of your system.&lt;/p&gt;

&lt;h1&gt;
  
  
  Levels of Abstraction ~ Levels of Testing
&lt;/h1&gt;

&lt;p&gt;Being able to replicate bugs quickly in some ways depends on testing capability. If I find a bug in the system and I have a testing architecture set up, then I can recreate the bug quickly and with minimal setup by running the test with a different input, or running the test a bit differently, or cloning a test setup and running it a different way. &lt;/p&gt;

&lt;p&gt;Example: you find a bug in prod and it's one of these "difficult to replicate" issues. At the very least you should have a test harness that works a starting point for replication. So many developers everywhere just run the thing from beginning to end, resulting in these ridiculous turnaround times. Testing is all about creating tests at the layers of complexity to replicate bugs, hopefully replicating them at the time you first write the code, but if necessary being able to use the test setup to do so.&lt;/p&gt;

&lt;h1&gt;
  
  
  Everything Converges to Iteration and Validation
&lt;/h1&gt;

&lt;p&gt;Especially today in the AI world. Consider that! If I have a complex system with many layers of hidden abstraction, and call a REST endpoint, the level of granularity of my response determines the quality of my feedback loop. And the feedback loop is everything in software, increasingly when you are trying to cost minimize with AI.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Good Code as a Data Structure</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Sun, 08 Sep 2024 12:16:07 +0000</pubDate>
      <link>https://dev.to/haydenrear/good-code-as-a-data-structure-g6h</link>
      <guid>https://dev.to/haydenrear/good-code-as-a-data-structure-g6h</guid>
      <description>&lt;p&gt;What do the frameworks have in common? How do you rectify the divide between object oriented and functional? How can we write code that can be provably correct, logically? One thing that has come up is modeling the "data", and even modeling a data structure.&lt;/p&gt;

&lt;p&gt;So when we write code that performs some actions, we want to prove that it performs the way we want it to in all cases. But then the number of cases grows to be out of control, resulting in wild edge cases. How to simplify? We make it a data structure that satisfies the needs. So then we only have one of iterate, add, remove, etc, and then we can add hooks into this data structure, such as afterAdd, afterRemove, postConstruct, and then we can build out our program as nodes that get added and perform behaviors after being added, removed, etc.&lt;/p&gt;

&lt;p&gt;One thing that's become viral is this idea of "hooks". We hook into the behavior in a way that we can prove. I argue that this is just that - a data structure that we hook into. &lt;/p&gt;

&lt;p&gt;So putting this together, we have a data structure that we can prove, and then we add hooks into that data structures behavior that we can prove things about. The nice thing about this is that it allows for the logic to be refined at various levels of the hierarchy, allowing reuse of the code and the logic to be refined correctly. &lt;/p&gt;

</description>
      <category>architecture</category>
      <category>cleancode</category>
      <category>datastructures</category>
    </item>
    <item>
      <title>10 Things You Should Be Thinking About Doing for the Coming AI Crisis: A Software Developer's Guide</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Wed, 02 Aug 2023 12:04:26 +0000</pubDate>
      <link>https://dev.to/haydenrear/10-things-you-should-be-thinking-about-doing-for-the-coming-ai-crisis-a-software-developers-guide-33n8</link>
      <guid>https://dev.to/haydenrear/10-things-you-should-be-thinking-about-doing-for-the-coming-ai-crisis-a-software-developers-guide-33n8</guid>
      <description>&lt;h1&gt;
  
  
  10 Things You Should Be Thinking About Doing for the Coming AI Crisis: A Software Developer's Guide
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The rise of AI is heralding a new era in technology, one that holds promises of innovation but also challenges that could disrupt many professional careers, including software development. The future is uncertain, but by preparing for it, software developers can transition their skills and stay ahead of the curve. Here are the ten things you should consider doing to navigate the coming AI crisis.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Embrace Lifelong Learning&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Understand the need for continuous education in the field of AI and machine learning.&lt;/li&gt;
&lt;li&gt;Participate in online courses, workshops, and AI-focused meetups.&lt;/li&gt;
&lt;li&gt;Stay up-to-date with the latest AI research, tools, and methodologies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Focus on Human-Centric Skills&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Improve skills that are difficult for AI to replicate, like creativity, critical thinking, empathy, and collaboration.&lt;/li&gt;
&lt;li&gt;Work on communication skills to bridge the gap between technology and business needs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Diversify Your Skillset&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Learn about adjacent fields like data science, cybersecurity, or UI/UX design.&lt;/li&gt;
&lt;li&gt;Pursue cross-disciplinary knowledge to enhance adaptability and resilience.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Build an AI-Ready Portfolio&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Include AI-related projects and contributions.&lt;/li&gt;
&lt;li&gt;Show off problem-solving skills using AI and machine learning.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Network with AI Professionals&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Engage with the AI community through social media, conferences, and local groups.&lt;/li&gt;
&lt;li&gt;Foster relationships with mentors and industry leaders.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Understand Ethical Considerations&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Study the ethical implications of AI in various contexts.&lt;/li&gt;
&lt;li&gt;Commit to responsible AI development and usage.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;strong&gt;Invest in AI Tool Mastery&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Learn and practice with leading AI frameworks and tools.&lt;/li&gt;
&lt;li&gt;Understand how to leverage cloud-based AI solutions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;strong&gt;Prepare for New Roles&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Identify emerging job roles that align with AI development.&lt;/li&gt;
&lt;li&gt;Consider shifting into specialized roles that require deep expertise.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. &lt;strong&gt;Contribute to Open Source Projects&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Engage with the global AI community through open source contributions.&lt;/li&gt;
&lt;li&gt;Enhance your skills and reputation by working on real-world problems.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. &lt;strong&gt;Think Globally, Act Locally&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subpoints:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Understand the global impact of AI on society and industries.&lt;/li&gt;
&lt;li&gt;Identify local opportunities and challenges and act accordingly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The coming AI crisis is both an opportunity and a challenge. By taking proactive steps, software developers can not only survive but thrive in this new era. The future belongs to those who are prepared, so begin the journey today by considering these ten pivotal aspects of professional transition.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>career</category>
    </item>
    <item>
      <title>Temporal Differencing vs Markov Chain Monte Carlo to Understand Model-Free, Model-Based, and Inverse Reinforcement Learning.</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Mon, 10 Jul 2023 13:48:35 +0000</pubDate>
      <link>https://dev.to/haydenrear/temporal-differencing-vs-markov-chain-monte-carlo-to-understand-model-free-model-based-and-inverse-reinforcement-learning-3aen</link>
      <guid>https://dev.to/haydenrear/temporal-differencing-vs-markov-chain-monte-carlo-to-understand-model-free-model-based-and-inverse-reinforcement-learning-3aen</guid>
      <description>&lt;h1&gt;
  
  
  Reinforcement Learning
&lt;/h1&gt;

&lt;p&gt;I remember the first lecture I watched on reinforcement learning. It was an MIT lecture about using a robot to bounce a ping-pong ball using a paddle. The lecturer discussed how in order for the machine to learn, it needed to "remember" the experiences in order to update it's ability. &lt;/p&gt;

&lt;p&gt;I had an AHA! moment, allowing me to realize how a machine could "learn". At the most extreme, it could be a table remembering each exact experience, and it could just try again and again until it succeeded, recording the successes and using the states previous to those successes to determine how to make the next second a "success". It could record a state and the action to take based on that state in order to maximize "success".&lt;/p&gt;

&lt;p&gt;However much I thought I knew in that moment, I failed to understand the complexity. It was one of those moments where I understood some very basic thing and generalized it to every possibility. In fact, to use reinforcement learning, you don't even need to be able to create "successes", but can learn as we go along if we have a way of extracting reward from the environment. Then, there is one step further: dynamically learning the reward function. Taking this step is almost "creepy". Not only does the agent learn as it goes along, it also learns how to learn by learning "what" to learn! This would be called "Inverse Reinforcement Learning".&lt;/p&gt;

&lt;h1&gt;
  
  
  Markov Chain Monte Carlo
&lt;/h1&gt;

&lt;p&gt;Monte Carlo methods are the foundations of a lot of important machine learning algorithms, including temporal differencing. I think that most machine learning algorithms can be understood in terms of Markov Chain Monte Carlo, such as &lt;a href="https://e2eml.school/transformers.html"&gt;Transformers&lt;/a&gt;. and Temporal Differencing. Markov Chain Monte Carlo is a model-based approach, meaning it extracts the "model" from the environment in the first step, and then samples from the environment to find the most desirable state based on the probability of retrieving a state from an action, and the reward of the states. &lt;/p&gt;

&lt;h1&gt;
  
  
  Temporal Differencing
&lt;/h1&gt;

&lt;p&gt;Temporal differencing takes this a step further. In Monte Carlo, we start with modeling the environment. Temporal differencing is more towards the "online" learning side. We start by initializing our model of the effect of the decisions arbitrarily. As we go along, we update the function that predicts the reward of the next state, and by "next state" I actually mean every state that I might take based on that state, often discounted. I am a chessmaster that is looking ahead into all of the moves at this point, discounting them. Or I am a really bad chess player who has no idea how to determine the moves. Hopefully you move from bad to good as time goes on. &lt;/p&gt;

&lt;p&gt;Really the model-based and model-free both have "models", but the definition of "model" is blurry in this context: &lt;/p&gt;

&lt;h1&gt;
  
  
  What is the "Model" in the context of model-based and model-free
&lt;/h1&gt;

&lt;p&gt;We talk about "model-based" and "model-free". But what is this "model"? The model can be thought of learning how to estimate the states, actions, and rewards, and how they relate to each other. If I am in a particular state, then these are my actions and this is the reward. This distinction between model-based and model-free lies in the environment dynamics. Does the model maintain some explicit idea of the transition dynamics of the environment based on the actions? Does the model then sample from this idea of the environment in order to determine which action to take? In the model-free algorithms, we learn a policy based on the state. In the model-based algorithms, we model the environment directly. It's a bit confusing because of course we have models, but in model-free we have a model that models the model of the environment, or something like that.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://arxiv.org/pdf/1806.06877.pdf"&gt;Inverse Reinforcement Learning&lt;/a&gt; as a Step from Model-Free
&lt;/h1&gt;

&lt;p&gt;If I thought of model-based as one step, moving towards "online", and then I took another step in that direction, model-free, then I would consider learning the reward function online as one step too far! &lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>reinforcementlearning</category>
      <category>temporaldifferencing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Effect Handlers in Functional Programming</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Sun, 21 May 2023 13:49:51 +0000</pubDate>
      <link>https://dev.to/haydenrear/effect-handlers-in-functional-programming-3mek</link>
      <guid>https://dev.to/haydenrear/effect-handlers-in-functional-programming-3mek</guid>
      <description>&lt;p&gt;What are side effects in functional programming? Why are they used?&lt;/p&gt;

&lt;h1&gt;
  
  
  What is FP
&lt;/h1&gt;

&lt;p&gt;I am not going to bore you with the introduction you usually get. If you are reading this, then you already know about immutable state and pure functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  What are side effects?
&lt;/h1&gt;

&lt;p&gt;You probably know what side effects are, but I'll talk about them here. Side effects are something that is something that causes an effect to happen outside of the application. They are introductions of instability into your pure code. They are toxicity in the water. We must manage them well if we maintain reasonability in our code. &lt;/p&gt;

&lt;p&gt;For example, let's say I am creating a new age database. This new age database is distributed, and says that it is consistent, but it's eventual consistency hinges on the fact that the interactions with the database are compiled WASM modules. The WASM modules are passed in, with an identifier for the component that is interacting with the database.&lt;/p&gt;

&lt;p&gt;Every time that a new behavior is added to the database, query is pre-registered. Then, the component that interacts with the database sends the parameters to the query. The query sits in the databases stack and on a clock when all the nodes of the database confirm, they are committed. &lt;/p&gt;

&lt;p&gt;But here's the thing: if the nodes disagree on the ordering of a transaction, the transactions can be reordered, and that means that the output of the transaction changes. So the user includes their transaction ID, and all is well. The transactions are re-ordered and re-executed on the stack, and everything is fine. And I make billions of dollars overnight because I used the acronym WASM DB.&lt;/p&gt;

&lt;h1&gt;
  
  
  Side Effects Ruin Everything
&lt;/h1&gt;

&lt;p&gt;Unfortunately, there is something wrong with our WASM compiled distributed new-age ridiculous database. If the user receives a response, which is "eventually consistent", then that response is subject to change. Of course if they just continue interacting with the database with their component ID, then it will propagate up through the stack. Of course, if there is no question about the ordering of the transaction, then the result they ended up getting will be the result (and under normal circumstances they can trust the result), HOWEVER if they are to perform some action outside of the system with the result, and it turns out to be outdated, then - sorry - everything starts to fail. Let's say they write to a log with the result, and then some other component reads from that log, and performs some actions, such as locking a user account. The user calls in and says, "why did you lock my account?", or a thousand users call in all at once.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Properly Manage Side Effects
&lt;/h1&gt;

&lt;p&gt;Side effects are a part of life, sort of like shit in the ocean. So how do you introduce the impure into the pure, without making it impure? Here are a few ideas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have a pure function describe the effect.&lt;/li&gt;
&lt;li&gt;Have another function take the description of the effect and perform the actual side effect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What does this mean? We take some behavior of the system and have a deterministic output. Determinism is key, because at this point we have all the different possible outputs. And then we can write test cases for each one, if we are good enough :).&lt;/p&gt;

</description>
      <category>functionalreactiveprogramming</category>
      <category>functional</category>
      <category>sideeffects</category>
    </item>
    <item>
      <title>Transformer Attention Mechanism Intuition</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Sat, 13 May 2023 15:00:56 +0000</pubDate>
      <link>https://dev.to/haydenrear/transformer-attention-mechanism-intuition-4g1d</link>
      <guid>https://dev.to/haydenrear/transformer-attention-mechanism-intuition-4g1d</guid>
      <description>&lt;p&gt;Transformers are very important to modern society. I, at one point, thought that transformers were here from the devil to transform the world into chaos. At one time I thought they would transform the world into utopia. In any case, the power they possess is alluring. Where does it come from? What is attention? How does it result in such amazing feats?&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Attention?
&lt;/h1&gt;

&lt;p&gt;Attention mechanism is effectively a way to extract features from the input data. Like convolutional layers extract features from an image, so attention mechanisms extract features from language, or anything else that you input into it. It is used in Transformer to compare the sequence to itself, to predict the next word, but you could compare other things as well, using the same attention mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attention Heads as Information Channels
&lt;/h2&gt;

&lt;p&gt;To understand the intuition behind a transformer, you can think of them as setting up information channels between different parts of the sentences. If you have ever heard or studied convolutional neural networks, they are like a convolutional neural network on steroids. Essentially, the attention heads move across the sentence, and then they are compared to each other to see how they relate. These attention heads picking out parts of the sentences to compare to each other is like setting up information channels between different parts of the sentences, so that information can get through. Like a CNN uses the kernel to extract features in a square, moving it across the image, so the attention heads move across the sentence. The difference is that there are multiple attention heads, each moving across the sentence, which each set up channels between different parts and then compare them to each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key, Query, and Value Intuition
&lt;/h2&gt;

&lt;p&gt;I like to think of things in terms of y = mx + b. For a neural network, this is like a recursive relationship, where the m contains more y = mx + b, but the basic idea is that the m is calculated to find the relationship between y and x. Key, Query, and Value can be thought of, intuitively, like this, where the Key = Query * Value. For example, in a transformer encoder for language models, the key, query, and value are all the input sentence, because you are trying to see how the sentence relates to itself. This is why it's called self-attention, because we use the attention mechanism in such a way to set the key, query, and value to the same "self", which is the language input.&lt;/p&gt;

&lt;p&gt;The power of attention does not stop at self-attention, however. You can set the key and the query to the same, and then set the value to something else, to see how two inputs vary, to extract features from two different sequences. Effectively, attention is a way to extract features from sequences. The only problem is that when you set up that many channels, it can be costly. In fact, it is hard to imagine how badly the attention mechanism scales. This is why new ways to extract features that use or resemble attention mechanism are being created. It is difficult to do so well, however, because the power from the attention mechanism comes from the fact that there be a way for the information to flow through, and without having a "channel" set up for it to flow through, it will not be able to. This is why we use attention to set up multiple channels for each word, however in the future we will probably get better at predicting which channel to listen to.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>transformers</category>
      <category>attention</category>
    </item>
    <item>
      <title>MBeans</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Tue, 09 May 2023 00:11:09 +0000</pubDate>
      <link>https://dev.to/haydenrear/mbeans-3d5l</link>
      <guid>https://dev.to/haydenrear/mbeans-3d5l</guid>
      <description>&lt;p&gt;Java MBeans - how do you know which ones to scrape? How do they work? What in the world does this mean?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - pattern: 'java.lang&amp;lt;type=GarbageCollector, name=(.*)&amp;gt;&amp;lt;&amp;gt;CollectionCount'
    name: gc_collection_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Scraping MBeans
&lt;/h1&gt;

&lt;p&gt;The first thing to keep in mind is that MBeans use remote method invocation to get the metrics that the MBean exposes. One of the quarks of Java MBeans is the way that they are identified. Here is an example ObjectName:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java.lang:name=G1 Old Generation,type=GarbageCollector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is an example of some code where you create an MBean, and start to understand how they are indexed for a JMX Exporter with the ObjectName:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import javax.management.*;

public class Main {
    public static void main(String[] args) throws Exception {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("com.example:type=MyMBean,name=MyInstance");
        My mbean = new My();
        mbs.registerMBean(mbean, name);

        System.out.println("MBean registered. Press Enter to exit.");
        System.in.read();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And so the question is - how can everything be identified by a string? Does the ordering matter? In fact, after the domain and the type and name, there is a list of key value pairs, and those are the properties.&lt;/p&gt;

&lt;h1&gt;
  
  
  Properties vs. Attributes
&lt;/h1&gt;

&lt;p&gt;Properties are identifiers for the MBean. In the example, the properties are type and name. You can filter by properties using JMX in the above example. Attributes are the metrics we are exposing. In the example at the start, CollectionCount is the attribute. We can add a regex expression there as well, to expose all of the attributes. So you can also filter by attributes, in that you can only expose some of the attributes of an MBean. However, typically the properties are used to identify and filter the MBeans. You can do some cool stuff with MBeans, such as creating histograms with the different values that the attributes can have, and you do this using JMX Exporter type, which is completely different than the property "type" used to filter.&lt;/p&gt;

&lt;h2&gt;
  
  
  But where are the attributes?
&lt;/h2&gt;

&lt;p&gt;If you look at an MBean, you will see your standard getters and setters, providing access to the attributes. These getters and setters would then be called with RMI to provide access to the data that is exposed via your favorite JMX exporter.&lt;/p&gt;

&lt;p&gt;For the example at the beginning:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LvSATOv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hd2vybb9rlyhiy57kag1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LvSATOv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hd2vybb9rlyhiy57kag1.png" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here the collection count is exposed using the getter, getCollectionCount, and this method is called using RMI (remote method invocation) with JMX.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finding MBeans to Scrape
&lt;/h1&gt;

&lt;p&gt;The first aha moment, when it comes to Java MBeans, is having a nice user interface to look at them. And, fortunately, if you have Java JDK installed, you have that user interface installed, and it's called jconsole. So if you open up a terminal and type jconsole, and follow the prompts to connect to a Java process, then you'll see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---mi_CUgs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/diktp0jlfuwkj5su257u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---mi_CUgs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/diktp0jlfuwkj5su257u.png" alt="Image description" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the attribute, collectionCount. And so you can see how to provide the previous pattern to access the metrics for the MBeans.&lt;/p&gt;

&lt;h1&gt;
  
  
  "Types" of MBeans
&lt;/h1&gt;

&lt;p&gt;The last thing to keep in mind when it comes to Java MBeans is that there are two things called types. Welcome to a strongly typed language. In any case, when it comes to JMX exporter and Prometheus, there is not only the type of MBean, but there is also the type of value. Examples include counter and gauge. Counter would handle something like number of garbage collections, while gauge is some continuous value. Additionally, Java has attributeType in the MBeanAttributeInfo, which is a separate type of MBean. Quite confusing, however this attributeType is different from the type of value that Prometheus interprets.&lt;/p&gt;

&lt;h1&gt;
  
  
  What in the world was that?
&lt;/h1&gt;

&lt;p&gt;The starting snippet is a JMX exporter rule. It matches on the MBean type, and all the various attributes. In JMX, you define these rules to determine which MBeans are exposed to the outside through the JMX exporting.&lt;/p&gt;

</description>
      <category>java</category>
      <category>mbeans</category>
      <category>metric</category>
      <category>observability</category>
    </item>
    <item>
      <title>Kubernetes Services Evolution</title>
      <dc:creator>Hayden Rear</dc:creator>
      <pubDate>Mon, 08 May 2023 23:46:43 +0000</pubDate>
      <link>https://dev.to/haydenrear/kubernetes-services-evolution-414k</link>
      <guid>https://dev.to/haydenrear/kubernetes-services-evolution-414k</guid>
      <description>&lt;p&gt;Kubernetes is a complex piece of software. Over the years of learning about it, it seems to have become more complex - the more I learn, the more I realize I don't know. One thing that has become more clear, however, is networking. I was once confused as to how to allow pods to talk to each other, but no more. Here are the things that helped me understand Kubernetes Services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Services - NodePort, Load Balancers, and ExternalName
&lt;/h1&gt;

&lt;p&gt;Kubernetes allows communication in a number of different ways, and they are normally through a service, where we change the type in the yaml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 8080
  type: NodePort
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to think of Services as being like Pokemon that evolve. NodePort is like the first baby pokemon before it has evolved. It is the simplest way to expose a Service. It forwards the traffic to a set of pods from a port. Then the poke-service evolves into a LoadBalancer, which provides an external IP address, load balancing, and other features. Normally LoadBalancers are used in a cloud environment, which leads to the Ingress, which isn't a service at all. The Ingress provides a way to provide access to multiple services on different paths.&lt;/p&gt;

&lt;p&gt;Here is an example LoadBalancer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: service1
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  type: LoadBalancer
  selector:
    app: service1
  ports:
    - name: http
      port: 80
      targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: service2
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  type: LoadBalancer
  selector:
    app: service2
  ports:
    - name: http
      port: 80
      targetPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and Ingress:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: service1.example.com
    http:
      paths:
      - path: /service1
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              name: http
  - host: service2.example.com
    http:
      paths:
      - path: /service2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              name: http
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Load Balancer vs Ingress
&lt;/h2&gt;

&lt;p&gt;The difference between LoadBalancer and Ingress is a bit nuanced, but both LoadBalancer and Ingress require external implementation, such as ElasticLoadBalancer or Istio's Ingress Controller. Ingress controller's provide more advanced routing, such as based on URL Path, while the LoadBalancer implements a load balancing algorithm. Additionally, the Ingress can be the plugin point for much other features of Service Mesh, such as mTLS. LoadBalancer can provide access to multiple services, but it doesn't use the path rerouting.&lt;/p&gt;

&lt;h1&gt;
  
  
  Communication
&lt;/h1&gt;

&lt;p&gt;"But how do you make the service call?" - In order to make the service call, just use the name of the service!&lt;/p&gt;

&lt;p&gt;In this case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I could make the REST call like so, from the metadata.name:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://**my-service**/v1/make/some-call&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>helm</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
